macos: prototype new GDK backend for macOS
authorChristian Hergert <chergert@redhat.com>
Thu, 23 Apr 2020 23:36:46 +0000 (16:36 -0700)
committerChristian Hergert <chergert@redhat.com>
Tue, 21 Jul 2020 21:45:12 +0000 (14:45 -0700)
This is fairly substantial rewrite of the GDK backend for quartz and
renamed to macOS to allow for a greenfield implementation.

Many things have come across from the quartz implementation fairly
intact such as the eventloop integration design and discovery of
event windows from the NSEvent.

However much has been changed to fit in with the new GDK design and
how removal of child GdkWindow have been completely eliminated.
Furthermore, the new GdkPopup allows for regular NSWindow to be used
to provide popovers unlike the previous implementation.

The object design more closely follows the ideal for a GDK backend.

Views have been broken out into subclasses so that we can support
multiple GSK renderer paths such as GL and Cairo (and Metal in the
future). However mixed mode GL and Cairo will not be supported. Currently
only the Cairo renderer has been implemented.

A new frame clock implementation using CVDisplayLink provides more
accurate information about when to draw drawing the next frame. Some
testing will need to be done here to understand the power implications
of this.

This implementation has also gained edge snapping for CSD windows. Some
work was also done to ensure that CSD windows have opaque regions
registered with the display server.

     ** This is still very much a work-in-progress **

Some outstanding work that needs to be done:

 - Finish a GL context for macOS and alternate NSView for GL rendering
   (possibly using speciailized CALayer for OpenGL).
 - Input rework to ensure that we don't loose remapping of keys that was
   dropped from GDK during GTK 4 development.
 - Make sure input methods continue to work.
 - Drag-n-Drop is still very much a work in progress
 - High resolution input scrolling needs various work in GDK to land
   first before we can plumb that to NSEvent.
 - gtk/ has a number of things based on GDK_WINDOWING_QUARTZ that need
   to be updated to use the macOS backend.

But this is good enough to start playing with and breaking things which
is what I'd like to see.

104 files changed:
gdk/gdkconfig.h.meson
gdk/gdkdisplaymanager.c
gdk/macos/GdkMacosBaseView.c [new file with mode: 0644]
gdk/macos/GdkMacosBaseView.h [new file with mode: 0644]
gdk/macos/GdkMacosCairoSubview.c [new file with mode: 0644]
gdk/macos/GdkMacosCairoSubview.h [new file with mode: 0644]
gdk/macos/GdkMacosCairoView.c [new file with mode: 0644]
gdk/macos/GdkMacosCairoView.h [new file with mode: 0644]
gdk/macos/GdkMacosGLLayer.c [new file with mode: 0644]
gdk/macos/GdkMacosGLLayer.h [new file with mode: 0644]
gdk/macos/GdkMacosWindow.c [new file with mode: 0644]
gdk/macos/GdkMacosWindow.h [new file with mode: 0644]
gdk/macos/edgesnapping.c [new file with mode: 0644]
gdk/macos/edgesnapping.h [new file with mode: 0644]
gdk/macos/gdkdisplaylinksource.c [new file with mode: 0644]
gdk/macos/gdkdisplaylinksource.h [new file with mode: 0644]
gdk/macos/gdkmacos.h [new file with mode: 0644]
gdk/macos/gdkmacoscairocontext-private.h [new file with mode: 0644]
gdk/macos/gdkmacoscairocontext.c [new file with mode: 0644]
gdk/macos/gdkmacosclipboard-private.h [new file with mode: 0644]
gdk/macos/gdkmacosclipboard.c [new file with mode: 0644]
gdk/macos/gdkmacoscursor-private.h [new file with mode: 0644]
gdk/macos/gdkmacoscursor.c [new file with mode: 0644]
gdk/macos/gdkmacosdevice.c [new file with mode: 0644]
gdk/macos/gdkmacosdevice.h [new file with mode: 0644]
gdk/macos/gdkmacosdisplay-private.h [new file with mode: 0644]
gdk/macos/gdkmacosdisplay-settings.c [new file with mode: 0644]
gdk/macos/gdkmacosdisplay-translate.c [new file with mode: 0644]
gdk/macos/gdkmacosdisplay.c [new file with mode: 0644]
gdk/macos/gdkmacosdisplay.h [new file with mode: 0644]
gdk/macos/gdkmacosdrag-private.h [new file with mode: 0644]
gdk/macos/gdkmacosdrag.c [new file with mode: 0644]
gdk/macos/gdkmacosdragsurface-private.h [new file with mode: 0644]
gdk/macos/gdkmacosdragsurface.c [new file with mode: 0644]
gdk/macos/gdkmacoseventsource-private.h [new file with mode: 0644]
gdk/macos/gdkmacoseventsource.c [new file with mode: 0644]
gdk/macos/gdkmacosglcontext-private.h [new file with mode: 0644]
gdk/macos/gdkmacosglcontext.c [new file with mode: 0644]
gdk/macos/gdkmacosglcontext.h [new file with mode: 0644]
gdk/macos/gdkmacoskeymap-private.h [new file with mode: 0644]
gdk/macos/gdkmacoskeymap.c [new file with mode: 0644]
gdk/macos/gdkmacoskeymap.h [new file with mode: 0644]
gdk/macos/gdkmacosmonitor-private.h [new file with mode: 0644]
gdk/macos/gdkmacosmonitor.c [new file with mode: 0644]
gdk/macos/gdkmacosmonitor.h [new file with mode: 0644]
gdk/macos/gdkmacospopupsurface-private.h [new file with mode: 0644]
gdk/macos/gdkmacospopupsurface.c [new file with mode: 0644]
gdk/macos/gdkmacosseat-private.h [new file with mode: 0644]
gdk/macos/gdkmacosseat.c [new file with mode: 0644]
gdk/macos/gdkmacossurface-private.h [new file with mode: 0644]
gdk/macos/gdkmacossurface.c [new file with mode: 0644]
gdk/macos/gdkmacossurface.h [new file with mode: 0644]
gdk/macos/gdkmacostoplevelsurface-private.h [new file with mode: 0644]
gdk/macos/gdkmacostoplevelsurface.c [new file with mode: 0644]
gdk/macos/gdkmacosutils-private.h [new file with mode: 0644]
gdk/macos/meson.build [new file with mode: 0644]
gdk/meson.build
gdk/quartz/GdkQuartzNSWindow.c [deleted file]
gdk/quartz/GdkQuartzNSWindow.h [deleted file]
gdk/quartz/GdkQuartzView.c [deleted file]
gdk/quartz/GdkQuartzView.h [deleted file]
gdk/quartz/gdkcairocontext-quartz.c [deleted file]
gdk/quartz/gdkcairocontext-quartz.h [deleted file]
gdk/quartz/gdkcursor-quartz.c [deleted file]
gdk/quartz/gdkdevice-core-quartz.c [deleted file]
gdk/quartz/gdkdevicemanager-core-quartz.c [deleted file]
gdk/quartz/gdkdevicemanager-core-quartz.h [deleted file]
gdk/quartz/gdkdisplay-quartz.c [deleted file]
gdk/quartz/gdkdisplay-quartz.h [deleted file]
gdk/quartz/gdkdisplaymanager-quartz.c [deleted file]
gdk/quartz/gdkdnd-quartz.c [deleted file]
gdk/quartz/gdkdnd-quartz.h [deleted file]
gdk/quartz/gdkeventloop-quartz.c [deleted file]
gdk/quartz/gdkevents-quartz.c [deleted file]
gdk/quartz/gdkglcontext-quartz.c [deleted file]
gdk/quartz/gdkglcontext-quartz.h [deleted file]
gdk/quartz/gdkglobals-quartz.c [deleted file]
gdk/quartz/gdkkeys-quartz.c [deleted file]
gdk/quartz/gdkmonitor-quartz.c [deleted file]
gdk/quartz/gdkmonitor-quartz.h [deleted file]
gdk/quartz/gdkprivate-quartz.h [deleted file]
gdk/quartz/gdkquartz.h [deleted file]
gdk/quartz/gdkquartzcursor.h [deleted file]
gdk/quartz/gdkquartzdevice-core.h [deleted file]
gdk/quartz/gdkquartzdevicemanager-core.h [deleted file]
gdk/quartz/gdkquartzdisplay.h [deleted file]
gdk/quartz/gdkquartzdisplaymanager.h [deleted file]
gdk/quartz/gdkquartzdnd.h [deleted file]
gdk/quartz/gdkquartzkeys.h [deleted file]
gdk/quartz/gdkquartzmonitor.h [deleted file]
gdk/quartz/gdkquartzscreen.h [deleted file]
gdk/quartz/gdkquartzsurface.h [deleted file]
gdk/quartz/gdkquartzutils.h [deleted file]
gdk/quartz/gdkscreen-quartz.c [deleted file]
gdk/quartz/gdkscreen-quartz.h [deleted file]
gdk/quartz/gdkselection-quartz.c [deleted file]
gdk/quartz/gdksurface-quartz.c [deleted file]
gdk/quartz/gdksurface-quartz.h [deleted file]
gdk/quartz/gdkutils-quartz.c [deleted file]
gdk/quartz/meson.build [deleted file]
gdk/quartz/xcursors.h [deleted file]
gsk/gskrenderer.c
meson.build
meson_options.txt

index 80666b25f0e6ee7d07a48183cc7cb28564a7e44b..867b430e43712140b55393266dd23f0a0d20b3f5 100644 (file)
@@ -12,6 +12,7 @@ G_BEGIN_DECLS
 
 #mesondefine GDK_WINDOWING_X11
 #mesondefine GDK_WINDOWING_BROADWAY
+#mesondefine GDK_WINDOWING_MACOS
 #mesondefine GDK_WINDOWING_WAYLAND
 #mesondefine GDK_WINDOWING_WIN32
 
index 94ced0387e5c0ffc5a0ebc995ff7271724c37376..a17305fcbe50881142707e4929cbd179d237e4f7 100644 (file)
 #include "broadway/gdkprivate-broadway.h"
 #endif
 
+#ifdef GDK_WINDOWING_MACOS
+#include "macos/gdkmacosdisplay-private.h"
+#endif
+
 #ifdef GDK_WINDOWING_WIN32
 #include "win32/gdkwin32.h"
 #include "win32/gdkprivate-win32.h"
@@ -262,6 +266,9 @@ static GdkBackend gdk_backends[] = {
 #ifdef GDK_WINDOWING_QUARTZ
   { "quartz",   _gdk_quartz_display_open },
 #endif
+#ifdef GDK_WINDOWING_MACOS
+  { "macos",   _gdk_macos_display_open },
+#endif
 #ifdef GDK_WINDOWING_WIN32
   { "win32",    _gdk_win32_display_open },
 #endif
diff --git a/gdk/macos/GdkMacosBaseView.c b/gdk/macos/GdkMacosBaseView.c
new file mode 100644 (file)
index 0000000..c6750df
--- /dev/null
@@ -0,0 +1,718 @@
+/* GdkMacosBaseView.c
+ *
+ * Copyright 2005-2007 Imendio AB
+ * Copyright 2011 Hiroyuki Yamamoto
+ * Copyright 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#import "GdkMacosBaseView.h"
+#import "GdkMacosWindow.h"
+
+#include "gdkinternals.h"
+
+#include "gdkmacosdisplay-private.h"
+#include "gdkmacossurface-private.h"
+
+/* Text Input Client */
+#define TIC_MARKED_TEXT      "tic-marked-text"
+#define TIC_SELECTED_POS     "tic-selected-pos"
+#define TIC_SELECTED_LEN     "tic-selected-len"
+#define TIC_INSERT_TEXT      "tic-insert-text"
+#define TIC_IN_KEY_DOWN      "tic-in-key-down"
+
+/* GtkIMContext */
+#define GIC_CURSOR_RECT      "gic-cursor-rect"
+#define GIC_FILTER_KEY       "gic-filter-key"
+#define GIC_FILTER_PASSTHRU  0
+#define GIC_FILTER_FILTERED  1
+
+@implementation GdkMacosBaseView
+
+-(id)initWithFrame:(NSRect)frameRect
+{
+  if ((self = [super initWithFrame: frameRect]))
+    {
+      NSRect rect = NSMakeRect (0, 0, 0, 0);
+      NSTrackingAreaOptions options;
+
+      markedRange = NSMakeRange (NSNotFound, 0);
+      selectedRange = NSMakeRange (0, 0);
+      [self setValue: @(YES) forKey: @"postsFrameChangedNotifications"];
+
+      options = (NSTrackingMouseEnteredAndExited |
+                 NSTrackingMouseMoved |
+                 NSTrackingInVisibleRect |
+                 NSTrackingActiveAlways);
+      trackingArea = [[NSTrackingArea alloc] initWithRect:rect
+                                                  options:options
+                                                    owner:(id)self
+                                                 userInfo:nil];
+      [self addTrackingArea:trackingArea];
+    }
+
+  return self;
+}
+
+-(void)setNeedsDisplay:(BOOL)needsDisplay
+{
+  for (id child in [self subviews])
+    [child setNeedsDisplay:needsDisplay];
+}
+
+-(void)setOpaqueRegion:(cairo_region_t *)region
+{
+  /* Do nothing */
+}
+
+-(BOOL)acceptsFirstMouse
+{
+  return YES;
+}
+
+-(BOOL)mouseDownCanMoveWindow
+{
+  return NO;
+}
+
+-(BOOL)acceptsFirstResponder
+{
+  GDK_NOTE (EVENTS, g_message ("acceptsFirstResponder"));
+  return YES;
+}
+
+-(BOOL)becomeFirstResponder
+{
+  GDK_NOTE (EVENTS, g_message ("becomeFirstResponder"));
+  return YES;
+}
+
+-(BOOL)resignFirstResponder
+{
+  GDK_NOTE (EVENTS, g_message ("resignFirstResponder"));
+  return YES;
+}
+
+-(void)setNeedsInvalidateShadow: (BOOL)invalidate
+{
+  needsInvalidateShadow = invalidate;
+}
+
+-(NSTrackingArea *)trackingArea
+{
+  return trackingArea;
+}
+
+-(GdkMacosSurface *)gdkSurface
+{
+  return [(GdkMacosWindow *)[self window] gdkSurface];
+}
+
+-(GdkMacosDisplay *)gdkDisplay
+{
+  GdkMacosSurface *surface = [self gdkSurface];
+  GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (surface));
+
+  return GDK_MACOS_DISPLAY (display);
+}
+
+-(void)keyDown:(NSEvent *)theEvent
+{
+  /* NOTE: When user press Cmd+A, interpretKeyEvents: will call noop:
+   * method. When user press and hold A to show the accented char window,
+   * it consumed repeating key down events for key 'A' do NOT call
+   * any other method. We use this behavior to determine if this key
+   * down event is filtered by interpretKeyEvents.
+   */
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_FILTERED));
+
+  GDK_NOTE (EVENTS, g_message ("keyDown"));
+  [self interpretKeyEvents: [NSArray arrayWithObject: theEvent]];
+}
+
+-(void)flagsChanged: (NSEvent *)theEvent
+{
+}
+
+-(NSUInteger)characterIndexForPoint:(NSPoint)aPoint
+{
+  GDK_NOTE (EVENTS, g_message ("characterIndexForPoint"));
+  return 0;
+}
+
+-(NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange: (NSRangePointer)actualRange
+{
+  GdkRectangle *rect;
+
+  GDK_NOTE (EVENTS, g_message ("firstRectForCharacterRange"));
+
+  if ((rect = g_object_get_data (G_OBJECT ([self gdkSurface]), GIC_CURSOR_RECT)))
+    {
+      GdkMacosDisplay *display = [self gdkDisplay];
+      int ns_x, ns_y;
+
+      _gdk_macos_display_to_display_coords (display,
+                                            rect->x, rect->y + rect->height,
+                                            &ns_x, &ns_y);
+
+      return NSMakeRect (ns_x, ns_y, rect->width, rect->height);
+    }
+
+  return NSMakeRect (0, 0, 0, 0);
+}
+
+-(NSArray *)validAttributesForMarkedText
+{
+  GDK_NOTE (EVENTS, g_message ("validAttributesForMarkedText"));
+  return [NSArray arrayWithObjects: NSUnderlineStyleAttributeName, nil];
+}
+
+-(NSAttributedString *)attributedSubstringForProposedRange: (NSRange)aRange actualRange: (NSRangePointer)actualRange
+{
+  GDK_NOTE (EVENTS, g_message ("attributedSubstringForProposedRange"));
+  return nil;
+}
+
+-(BOOL)hasMarkedText
+{
+  GDK_NOTE (EVENTS, g_message ("hasMarkedText"));
+  return markedRange.location != NSNotFound && markedRange.length != 0;
+}
+
+-(NSRange)markedRange
+{
+  GDK_NOTE (EVENTS, g_message ("markedRange"));
+  return markedRange;
+}
+
+-(NSRange)selectedRange
+{
+  GDK_NOTE (EVENTS, g_message ("selectedRange"));
+  return selectedRange;
+}
+
+-(void)unmarkText
+{
+  GDK_NOTE (EVENTS, g_message ("unmarkText"));
+
+  selectedRange = NSMakeRange (0, 0);
+  markedRange = NSMakeRange (NSNotFound, 0);
+
+  g_object_set_data_full (G_OBJECT ([self gdkSurface]), TIC_MARKED_TEXT, NULL, g_free);
+}
+
+-(void)setMarkedText:(id)aString selectedRange: (NSRange)newSelection replacementRange: (NSRange)replacementRange
+{
+  const char *str;
+
+  GDK_NOTE (EVENTS, g_message ("setMarkedText"));
+
+  if (replacementRange.location == NSNotFound)
+    {
+      markedRange = NSMakeRange (newSelection.location, [aString length]);
+      selectedRange = NSMakeRange (newSelection.location, newSelection.length);
+    }
+  else
+    {
+      markedRange = NSMakeRange (replacementRange.location, [aString length]);
+      selectedRange = NSMakeRange (replacementRange.location + newSelection.location, newSelection.length);
+    }
+
+  if ([aString isKindOfClass: [NSAttributedString class]])
+    str = [[aString string] UTF8String];
+  else
+    str = [aString UTF8String];
+
+  g_object_set_data_full (G_OBJECT ([self gdkSurface]), TIC_MARKED_TEXT, g_strdup (str), g_free);
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     TIC_SELECTED_POS,
+                     GUINT_TO_POINTER (selectedRange.location));
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     TIC_SELECTED_LEN,
+                     GUINT_TO_POINTER (selectedRange.length));
+
+  GDK_NOTE (EVENTS, g_message ("setMarkedText: set %s (%p, nsview %p): %s",
+                               TIC_MARKED_TEXT, [self gdkSurface], self,
+                               str ? str : "(empty)"));
+
+  /* handle text input changes by mouse events */
+  if (!GPOINTER_TO_UINT (g_object_get_data (G_OBJECT ([self gdkSurface]), TIC_IN_KEY_DOWN)))
+    _gdk_macos_surface_synthesize_null_key ([self gdkSurface]);
+}
+
+-(void)doCommandBySelector:(SEL)aSelector
+{
+  GDK_NOTE (EVENTS, g_message ("doCommandBySelector"));
+
+  if ([self respondsToSelector: aSelector])
+    [self performSelector: aSelector];
+}
+
+-(void)insertText:(id)aString replacementRange: (NSRange)replacementRange
+{
+  const char *str;
+  NSString *string;
+
+  GDK_NOTE (EVENTS, g_message ("insertText"));
+
+  if ([self hasMarkedText])
+    [self unmarkText];
+
+  if ([aString isKindOfClass: [NSAttributedString class]])
+    string = [aString string];
+  else
+    string = aString;
+
+  NSCharacterSet *ctrlChars = [NSCharacterSet controlCharacterSet];
+  NSCharacterSet *wsnlChars = [NSCharacterSet whitespaceAndNewlineCharacterSet];
+  if ([string rangeOfCharacterFromSet:ctrlChars].length &&
+      [string rangeOfCharacterFromSet:wsnlChars].length == 0)
+    {
+      /* discard invalid text input with Chinese input methods */
+      str = "";
+      [self unmarkText];
+      [[NSTextInputContext currentInputContext] discardMarkedText];
+    }
+  else
+   {
+      str = [string UTF8String];
+   }
+
+  g_object_set_data_full (G_OBJECT ([self gdkSurface]), TIC_INSERT_TEXT, g_strdup (str), g_free);
+  GDK_NOTE (EVENTS, g_message ("insertText: set %s (%p, nsview %p): %s",
+                               TIC_INSERT_TEXT, [self gdkSurface], self,
+                               str ? str : "(empty)"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_FILTERED));
+
+  /* handle text input changes by mouse events */
+  if (!GPOINTER_TO_UINT (g_object_get_data (G_OBJECT ([self gdkSurface]), TIC_IN_KEY_DOWN)))
+    _gdk_macos_surface_synthesize_null_key ([self gdkSurface]);
+}
+
+-(void)deleteBackward:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("deleteBackward"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)deleteForward:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("deleteForward"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)deleteToBeginningOfLine:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("deleteToBeginningOfLine"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)deleteToEndOfLine:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("deleteToEndOfLine"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)deleteWordBackward:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("deleteWordBackward"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)deleteWordForward:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("deleteWordForward"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)insertBacktab:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("insertBacktab"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)insertNewline:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("insertNewline"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)insertTab:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("insertTab"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveBackward:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveBackward"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveBackwardAndModifySelection:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveBackwardAndModifySelection"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveDown:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveDown"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveDownAndModifySelection:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveDownAndModifySelection"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveForward:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveForward"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveForwardAndModifySelection:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveForwardAndModifySelection"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveLeft:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveLeft"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveLeftAndModifySelection:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveLeftAndModifySelection"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveRight:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveRight"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveRightAndModifySelection:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveRightAndModifySelection"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveToBeginningOfDocument:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveToBeginningOfDocument"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveToBeginningOfDocumentAndModifySelection:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveToBeginningOfDocumentAndModifySelection"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveToBeginningOfLine:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveToBeginningOfLine"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveToBeginningOfLineAndModifySelection:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveToBeginningOfLineAndModifySelection"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveToEndOfDocument:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveToEndOfDocument"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveToEndOfDocumentAndModifySelection:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveToEndOfDocumentAndModifySelection"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveToEndOfLine:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveToEndOfLine"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveToEndOfLineAndModifySelection:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveToEndOfLineAndModifySelection"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveUp:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveUp"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveUpAndModifySelection:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveUpAndModifySelection"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveWordBackward:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveWordBackward"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveWordBackwardAndModifySelection:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveWordBackwardAndModifySelection"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveWordForward:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveWordForward"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveWordForwardAndModifySelection:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveWordForwardAndModifySelection"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveWordLeft:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveWordLeft"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveWordLeftAndModifySelection:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveWordLeftAndModifySelection"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveWordRight:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveWordRight"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)moveWordRightAndModifySelection:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("moveWordRightAndModifySelection"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)pageDown:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("pageDown"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)pageDownAndModifySelection:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("pageDownAndModifySelection"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)pageUp:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("pageUp"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)pageUpAndModifySelection:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("pageUpAndModifySelection"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)selectAll:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("selectAll"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)selectLine:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("selectLine"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)selectWord:(id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("selectWord"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+-(void)noop: (id)sender
+{
+  GDK_NOTE (EVENTS, g_message ("noop"));
+
+  g_object_set_data (G_OBJECT ([self gdkSurface]),
+                     GIC_FILTER_KEY,
+                     GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
+}
+
+@end
diff --git a/gdk/macos/GdkMacosBaseView.h b/gdk/macos/GdkMacosBaseView.h
new file mode 100644 (file)
index 0000000..7fcfc7e
--- /dev/null
@@ -0,0 +1,46 @@
+/* GdkMacosBaseView.h
+ *
+ * Copyright © 2020 Red Hat, Inc.
+ * Copyright © 2005-2007 Imendio AB
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#import <AppKit/AppKit.h>
+#import <Foundation/Foundation.h>
+
+#include <gdk/gdk.h>
+
+#include "gdkmacosdisplay.h"
+#include "gdkmacossurface.h"
+
+#define GDK_IS_MACOS_BASE_VIEW(obj) ((obj) && [obj isKindOfClass:[GdkMacosBaseView class]])
+
+@interface GdkMacosBaseView : NSView <NSTextInputClient>
+{
+  NSTrackingArea *trackingArea;
+  BOOL needsInvalidateShadow;
+  NSRange markedRange;
+  NSRange selectedRange;
+}
+
+-(GdkMacosSurface *)gdkSurface;
+-(GdkMacosDisplay *)gdkDisplay;
+-(void)setNeedsInvalidateShadow: (BOOL)invalidate;
+-(NSTrackingArea *)trackingArea;
+-(void)setOpaqueRegion:(cairo_region_t *)region;
+
+@end
diff --git a/gdk/macos/GdkMacosCairoSubview.c b/gdk/macos/GdkMacosCairoSubview.c
new file mode 100644 (file)
index 0000000..425b52a
--- /dev/null
@@ -0,0 +1,171 @@
+/* GdkMacosCairoSubview.c
+ *
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include <CoreGraphics/CoreGraphics.h>
+#include <cairo-quartz.h>
+
+#include "gdkinternals.h"
+
+#import "GdkMacosCairoSubview.h"
+#import "GdkMacosCairoView.h"
+
+#include "gdkmacossurface-private.h"
+
+@implementation GdkMacosCairoSubview
+
+-(BOOL)isOpaque
+{
+  return _isOpaque;
+}
+
+-(BOOL)isFlipped
+{
+  return YES;
+}
+
+-(GdkSurface *)gdkSurface
+{
+  return GDK_SURFACE ([(GdkMacosBaseView *)[self superview] gdkSurface]);
+}
+
+-(void)drawRect:(NSRect)rect
+{
+  CGContextRef cgContext;
+  GdkSurface *gdk_surface;
+  cairo_surface_t *dest;
+  const NSRect *rects = NULL;
+  NSView *root_view;
+  NSInteger n_rects = 0;
+  NSRect abs_bounds;
+  cairo_t *cr;
+  CGSize scale;
+  int scale_factor;
+
+  if (self->cairoSurface == NULL)
+    return;
+
+  /* Acquire everything we need to do translations, drawing, etc */
+  gdk_surface = [self gdkSurface];
+  scale_factor = gdk_surface_get_scale_factor (gdk_surface);
+  root_view = [[self window] contentView];
+  cgContext = [[NSGraphicsContext currentContext] CGContext];
+  abs_bounds = [self convertRect:[self bounds] toView:root_view];
+
+  CGContextSaveGState (cgContext);
+
+  /* Translate scaling to remove HiDPI scaling from CGContext as
+   * cairo will be doing that for us already.
+   */
+  scale = CGSizeMake (1.0, 1.0);
+  scale = CGContextConvertSizeToDeviceSpace (cgContext, scale);
+  CGContextScaleCTM (cgContext, 1.0 / scale.width, 1.0 / scale.height);
+
+  /* Create the cairo surface to draw to the CGContext and translate
+   * coordinates so we can pretend we are in the same coordinate system
+   * as the GDK surface.
+   */
+  dest = cairo_quartz_surface_create_for_cg_context (cgContext,
+                                                     gdk_surface->width * scale_factor,
+                                                     gdk_surface->height * scale_factor);
+  cairo_surface_set_device_scale (dest, scale_factor, scale_factor);
+
+  /* Create cairo context and translate things into the origin of
+   * the topmost contentView so that we just draw at 0,0 with a
+   * clip region to paint the surface.
+   */
+  cr = cairo_create (dest);
+  cairo_translate (cr, -abs_bounds.origin.x, -abs_bounds.origin.y);
+
+  /* Clip the cairo context based on the rectangles to be drawn
+   * within the bounding box :rect.
+   */
+  [self getRectsBeingDrawn:&rects count:&n_rects];
+  for (NSInteger i = 0; i < n_rects; i++)
+    {
+      NSRect area = [self convertRect:rects[i] toView:root_view];
+      cairo_rectangle (cr,
+                       area.origin.x, area.origin.y,
+                       area.size.width, area.size.height);
+    }
+  cairo_clip (cr);
+
+  /* Now paint the surface (without blending) as we do not need
+   * any compositing here. The transparent regions (like shadows)
+   * are already on non-opaque layers.
+   */
+  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+  cairo_set_source_surface (cr, self->cairoSurface, 0, 0);
+  cairo_paint (cr);
+
+  /* Cleanup state, flush the surface to the backing layer, and
+   * restore GState for future use.
+   */
+  cairo_destroy (cr);
+  cairo_surface_flush (dest);
+  cairo_surface_destroy (dest);
+  CGContextRestoreGState (cgContext);
+}
+
+-(void)setCairoSurface:(cairo_surface_t *)surface
+            withDamage:(cairo_region_t *)region
+{
+  if (surface != self->cairoSurface)
+    {
+      g_clear_pointer (&self->cairoSurface, cairo_surface_destroy);
+      if (surface != NULL)
+        self->cairoSurface = cairo_surface_reference (surface);
+    }
+
+  if (region != NULL)
+    {
+      NSView *root_view = [[self window] contentView];
+      NSRect abs_bounds = [self convertRect:[self bounds] toView:root_view];
+      guint n_rects = cairo_region_num_rectangles (region);
+
+      for (guint i = 0; i < n_rects; i++)
+        {
+          cairo_rectangle_int_t rect;
+          NSRect nsrect;
+
+          cairo_region_get_rectangle (region, i, &rect);
+          nsrect = NSMakeRect (rect.x, rect.y, rect.width, rect.height);
+
+          if (NSIntersectsRect (abs_bounds, nsrect))
+            {
+              nsrect.origin.x -= abs_bounds.origin.x;
+              nsrect.origin.y -= abs_bounds.origin.y;
+              [self setNeedsDisplayInRect:nsrect];
+            }
+        }
+    }
+
+  for (id view in [self subviews])
+    [(GdkMacosCairoSubview *)view setCairoSurface:surface
+                                       withDamage:region];
+}
+
+-(void)setOpaque:(BOOL)opaque
+{
+  self->_isOpaque = opaque;
+}
+
+@end
diff --git a/gdk/macos/GdkMacosCairoSubview.h b/gdk/macos/GdkMacosCairoSubview.h
new file mode 100644 (file)
index 0000000..9255347
--- /dev/null
@@ -0,0 +1,35 @@
+/* GdkMacosCairoSubview.h
+ *
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include <AppKit/AppKit.h>
+
+#define GDK_IS_MACOS_CAIRO_SUBVIEW(obj) ((obj) && [obj isKindOfClass:[GdkMacosCairoSubview class]])
+
+@interface GdkMacosCairoSubview : NSView
+{
+  BOOL             _isOpaque;
+  cairo_surface_t *cairoSurface;
+}
+
+-(void)setOpaque:(BOOL)opaque;
+-(void)setCairoSurface:(cairo_surface_t *)cairoSurface
+            withDamage:(cairo_region_t *)region;
+
+@end
diff --git a/gdk/macos/GdkMacosCairoView.c b/gdk/macos/GdkMacosCairoView.c
new file mode 100644 (file)
index 0000000..e6a3117
--- /dev/null
@@ -0,0 +1,170 @@
+/* GdkMacosCairoView.c
+ *
+ * Copyright © 2020 Red Hat, Inc.
+ * Copyright © 2005-2007 Imendio AB
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include <CoreGraphics/CoreGraphics.h>
+#include <cairo-quartz.h>
+
+#include "gdkinternals.h"
+
+#import "GdkMacosCairoView.h"
+#import "GdkMacosCairoSubview.h"
+
+#include "gdkmacossurface-private.h"
+
+@implementation GdkMacosCairoView
+
+-(void)dealloc
+{
+  g_clear_pointer (&self->opaque, g_ptr_array_unref);
+  self->transparent = NULL;
+
+  [super dealloc];
+}
+
+-(BOOL)isOpaque
+{
+  if ([self window])
+    return [[self window] isOpaque];
+  return YES;
+}
+
+-(BOOL)isFlipped
+{
+  return YES;
+}
+
+-(void)setCairoSurface:(cairo_surface_t *)cairoSurface
+            withDamage:(cairo_region_t *)cairoRegion
+{
+  for (id view in [self subviews])
+    [(GdkMacosCairoSubview *)view setCairoSurface:cairoSurface
+                                       withDamage:cairoRegion];
+}
+
+-(void)removeOpaqueChildren
+{
+  [[self->transparent subviews]
+    makeObjectsPerformSelector:@selector(removeFromSuperview)];
+
+  if (self->opaque->len)
+    g_ptr_array_remove_range (self->opaque, 0, self->opaque->len);
+}
+
+-(void)setOpaqueRegion:(cairo_region_t *)region
+{
+  NSRect abs_bounds;
+  guint n_rects;
+
+  if (region == NULL)
+    return;
+
+  abs_bounds = [self convertRect:[self bounds] toView:nil];
+  n_rects = cairo_region_num_rectangles (region);
+
+  /* The common case (at least for opaque windows and CSD) is that we will
+   * have either one or two opaque rectangles. If we detect that the same
+   * number of them are available as the previous, we can just resize the
+   * previous ones to avoid adding/removing views at a fast rate while
+   * resizing.
+   */
+  if (n_rects == self->opaque->len)
+    {
+      for (guint i = 0; i < n_rects; i++)
+        {
+          GdkMacosCairoSubview *child;
+          cairo_rectangle_int_t rect;
+
+          child = g_ptr_array_index (self->opaque, i);
+          cairo_region_get_rectangle (region, i, &rect);
+
+          [child setFrame:NSMakeRect (rect.x - abs_bounds.origin.x,
+                                      rect.y - abs_bounds.origin.y,
+                                      rect.width,
+                                      rect.height)];
+        }
+
+      return;
+    }
+
+  [self removeOpaqueChildren];
+  for (guint i = 0; i < n_rects; i++)
+    {
+      GdkMacosCairoSubview *child;
+      cairo_rectangle_int_t rect;
+      NSRect nsrect;
+
+      cairo_region_get_rectangle (region, i, &rect);
+      nsrect = NSMakeRect (rect.x - abs_bounds.origin.x,
+                           rect.y - abs_bounds.origin.y,
+                           rect.width,
+                           rect.height);
+
+      child = [[GdkMacosCairoSubview alloc] initWithFrame:nsrect];
+      [child setOpaque:YES];
+      [child setWantsLayer:YES];
+      [self->transparent addSubview:child];
+      g_ptr_array_add (self->opaque, child);
+    }
+}
+
+-(NSView *)initWithFrame:(NSRect)frame
+{
+  if ((self = [super initWithFrame:frame]))
+    {
+      /* An array to track all the opaque children placed into
+       * the child self->transparent. This allows us to reuse them
+       * when we receive a new opaque area instead of discarding
+       * them on each draw.
+       */
+      self->opaque = g_ptr_array_new ();
+
+      /* Setup our primary subview which will render all content that is not
+       * within an opaque region (such as shadows for CSD windows). For opaque
+       * windows, this will all be obscurred by other views, so it doesn't
+       * matter much to have it here.
+       */
+      self->transparent = [[GdkMacosCairoSubview alloc] initWithFrame:frame];
+      [self addSubview:self->transparent];
+
+    }
+
+  return self;
+}
+
+-(void)setFrame:(NSRect)rect
+{
+  [super setFrame:rect];
+  [self->transparent setFrame:NSMakeRect (0, 0, rect.size.width, rect.size.height)];
+}
+
+-(BOOL)acceptsFirstMouse
+{
+  return YES;
+}
+
+-(BOOL)mouseDownCanMoveWindow
+{
+  return NO;
+}
+
+@end
diff --git a/gdk/macos/GdkMacosCairoView.h b/gdk/macos/GdkMacosCairoView.h
new file mode 100644 (file)
index 0000000..1c28d83
--- /dev/null
@@ -0,0 +1,37 @@
+/* GdkMacosCairoView.h
+ *
+ * Copyright © 2020 Red Hat, Inc.
+ * Copyright © 2005-2007 Imendio AB
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include <cairo.h>
+
+#import "GdkMacosBaseView.h"
+
+#define GDK_IS_MACOS_CAIRO_VIEW(obj) ((obj) && [obj isKindOfClass:[GdkMacosCairoView class]])
+
+@interface GdkMacosCairoView : GdkMacosBaseView
+{
+  NSView *transparent;
+  GPtrArray *opaque;
+}
+
+-(void)setCairoSurface:(cairo_surface_t *)cairoSurface
+            withDamage:(cairo_region_t *)region;
+
+@end
diff --git a/gdk/macos/GdkMacosGLLayer.c b/gdk/macos/GdkMacosGLLayer.c
new file mode 100644 (file)
index 0000000..a1ab55a
--- /dev/null
@@ -0,0 +1,157 @@
+/* GdkMacosGLLayer.c
+ *
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/* Based on Chromium image_transport_surface_calayer_mac.mm
+ * See the BSD-style license above.
+ */
+
+#include "config.h"
+
+#include <OpenGL/gl.h>
+
+#import "GdkMacosGLLayer.h"
+
+@implementation GdkMacosGLLayer
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+
+-(id)initWithContext:(NSOpenGLContext *)shared
+{
+  [super init];
+  _shared = [shared retain];
+  return self;
+}
+
+-(void)dealloc
+{
+  [_shared release];
+  _shared = nil;
+
+  [super dealloc];
+}
+
+-(void)setContentsRect:(NSRect)bounds
+{
+  _pixelSize = bounds.size;
+  [super setContentsRect:bounds];
+}
+
+-(CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask
+{
+  return CGLRetainPixelFormat ([[_shared pixelFormat] CGLPixelFormatObj]);
+}
+
+-(CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat
+{
+  CGLContextObj context = NULL;
+  CGLCreateContext (pixelFormat, [_shared CGLContextObj], &context);
+  return context;
+}
+
+-(BOOL)canDrawInCGLContext:(CGLContextObj)glContext
+               pixelFormat:(CGLPixelFormatObj)pixelFormat
+              forLayerTime:(CFTimeInterval)timeInterval
+               displayTime:(const CVTimeStamp*)timeStamp
+{
+  return YES;
+}
+
+-(void)drawInCGLContext:(CGLContextObj)glContext
+            pixelFormat:(CGLPixelFormatObj)pixelFormat
+           forLayerTime:(CFTimeInterval)timeInterval
+            displayTime:(const CVTimeStamp*)timeStamp
+{
+  if (_texture == 0)
+    return;
+
+  glClearColor (1, 0, 1, 1);
+  glClear (GL_COLOR_BUFFER_BIT);
+  GLint viewport[4] = {0, 0, 0, 0};
+  glGetIntegerv (GL_VIEWPORT, viewport);
+  NSSize viewportSize = NSMakeSize (viewport[2], viewport[3]);
+
+  /* Set the coordinate system to be one-to-one with pixels. */
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity ();
+  glOrtho (0, viewportSize.width, 0, viewportSize.height, -1, 1);
+  glMatrixMode (GL_MODELVIEW);
+  glLoadIdentity ();
+
+  /* Draw a fullscreen quad. */
+  glColor4f (1, 1, 1, 1);
+  glEnable (GL_TEXTURE_RECTANGLE_ARB);
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, _texture);
+  glBegin (GL_QUADS);
+  {
+    glTexCoord2f (0, 0);
+    glVertex2f (0, 0);
+    glTexCoord2f (0, _pixelSize.height);
+    glVertex2f (0, _pixelSize.height);
+    glTexCoord2f (_pixelSize.width, _pixelSize.height);
+    glVertex2f (_pixelSize.width, _pixelSize.height);
+    glTexCoord2f (_pixelSize.width, 0);
+    glVertex2f (_pixelSize.width, 0);
+  }
+  glEnd ();
+  glBindTexture (0, _texture);
+  glDisable (GL_TEXTURE_RECTANGLE_ARB);
+  [super drawInCGLContext:glContext
+              pixelFormat:pixelFormat
+             forLayerTime:timeInterval
+              displayTime:timeStamp];
+}
+
+-(void)setTexture:(GLuint)texture
+{
+  _texture = texture;
+  [self setNeedsDisplay];
+}
+
+G_GNUC_END_IGNORE_DEPRECATIONS
+
+@end
diff --git a/gdk/macos/GdkMacosGLLayer.h b/gdk/macos/GdkMacosGLLayer.h
new file mode 100644 (file)
index 0000000..dd90c1c
--- /dev/null
@@ -0,0 +1,40 @@
+/* GdkMacosGLLayer.h
+ *
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include <AppKit/AppKit.h>
+#include <glib.h>
+
+#define GDK_IS_MACOS_GL_LAYER(obj) ((obj) && [obj isKindOfClass:[GdkMacosGLLayer class]])
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+
+@interface GdkMacosGLLayer : CAOpenGLLayer
+{
+  NSOpenGLContext *_shared;
+  GLuint _texture;
+  NSSize _pixelSize;
+}
+
+-(id)initWithContext:(NSOpenGLContext *)shared;
+-(void)setTexture:(GLuint)texture;
+
+@end
+
+G_GNUC_END_IGNORE_DEPRECATIONS
diff --git a/gdk/macos/GdkMacosWindow.c b/gdk/macos/GdkMacosWindow.c
new file mode 100644 (file)
index 0000000..6ba8780
--- /dev/null
@@ -0,0 +1,732 @@
+/* GdkMacosWindow.m
+ *
+ * Copyright © 2020 Red Hat, Inc.
+ * Copyright © 2005-2007 Imendio AB
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include <gdk/gdk.h>
+
+#import "GdkMacosBaseView.h"
+#import "GdkMacosCairoView.h"
+#import "GdkMacosWindow.h"
+
+#include "gdkmacosdisplay-private.h"
+#include "gdkmacossurface-private.h"
+#include "gdkmacospopupsurface-private.h"
+#include "gdkmacostoplevelsurface-private.h"
+
+#include "gdkmonitorprivate.h"
+#include "gdksurfaceprivate.h"
+
+@implementation GdkMacosWindow
+
+-(BOOL)windowShouldClose:(id)sender
+{
+  GdkDisplay *display;
+  GdkEvent *event;
+  GList *node;
+
+  display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
+  event = gdk_delete_event_new (GDK_SURFACE (gdk_surface));
+  node = _gdk_event_queue_append (display, event);
+  _gdk_windowing_got_event (display, node, event,
+                            _gdk_display_get_next_serial (display));
+
+  return NO;
+}
+
+-(void)windowWillMiniaturize:(NSNotification *)aNotification
+{
+  if (GDK_IS_MACOS_TOPLEVEL_SURFACE (gdk_surface))
+    _gdk_macos_toplevel_surface_detach_from_parent (GDK_MACOS_TOPLEVEL_SURFACE (gdk_surface));
+  else if (GDK_IS_MACOS_POPUP_SURFACE (gdk_surface))
+    _gdk_macos_popup_surface_detach_from_parent (GDK_MACOS_POPUP_SURFACE (gdk_surface));
+}
+
+-(void)windowDidMiniaturize:(NSNotification *)aNotification
+{
+  gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), 0, GDK_SURFACE_STATE_MINIMIZED);
+}
+
+-(void)windowDidDeminiaturize:(NSNotification *)aNotification
+{
+  if (GDK_IS_MACOS_TOPLEVEL_SURFACE (gdk_surface))
+    _gdk_macos_toplevel_surface_attach_to_parent (GDK_MACOS_TOPLEVEL_SURFACE (gdk_surface));
+  else if (GDK_IS_MACOS_POPUP_SURFACE (gdk_surface))
+    _gdk_macos_popup_surface_attach_to_parent (GDK_MACOS_POPUP_SURFACE (gdk_surface));
+
+  gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), GDK_SURFACE_STATE_MINIMIZED, 0);
+}
+
+-(void)windowDidBecomeKey:(NSNotification *)aNotification
+{
+  gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), 0, GDK_SURFACE_STATE_FOCUSED);
+  _gdk_macos_display_surface_became_key ([self gdkDisplay], gdk_surface);
+}
+
+-(void)windowDidResignKey:(NSNotification *)aNotification
+{
+  gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), GDK_SURFACE_STATE_FOCUSED, 0);
+  _gdk_macos_display_surface_resigned_key ([self gdkDisplay], gdk_surface);
+}
+
+-(void)windowDidBecomeMain:(NSNotification *)aNotification
+{
+  if (![self isVisible])
+    {
+      /* Note: This is a hack needed because for unknown reasons, hidden
+       * windows get shown when clicking the dock icon when the application
+       * is not already active.
+       */
+      [self orderOut:nil];
+      return;
+    }
+
+  _gdk_macos_display_surface_became_main ([self gdkDisplay], gdk_surface);
+}
+
+-(void)windowDidResignMain:(NSNotification *)aNotification
+{
+  _gdk_macos_display_surface_resigned_main ([self gdkDisplay], gdk_surface);
+}
+
+/* Used in combination with NSLeftMouseUp in sendEvent to keep track
+ * of when the window is being moved with the mouse.
+ */
+-(void)windowWillMove:(NSNotification *)aNotification
+{
+  inMove = YES;
+}
+
+-(void)sendEvent:(NSEvent *)event
+{
+  NSEventType event_type = [event type];
+
+  switch ((int)event_type)
+    {
+    case NSEventTypeLeftMouseUp: {
+      GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
+      double time = ((double)[event timestamp]) * 1000.0;
+
+      _gdk_macos_display_break_all_grabs (GDK_MACOS_DISPLAY (display), time);
+
+      inManualMove = NO;
+      inManualResize = NO;
+      inMove = NO;
+
+      /* We need to deliver the event to the proper drag gestures or we
+       * will leave the window in inconsistent state that requires clicking
+       * in the window to cancel the gesture.
+       *
+       * TODO: Can we improve grab breaking to fix this?
+       */
+      _gdk_macos_display_send_button_event ([self gdkDisplay], event);
+
+      break;
+    }
+
+    case NSEventTypeLeftMouseDragged:
+      if ([self trackManualMove] || [self trackManualResize])
+        return;
+      break;
+
+    default:
+      break;
+    }
+
+  [super sendEvent:event];
+}
+
+-(BOOL)isInMove
+{
+  return inMove;
+}
+
+-(void)checkSendEnterNotify
+{
+  /* When a new window has been created, and the mouse is in the window
+   * area, we will not receive an NSEventTypeMouseEntered event.
+   * Therefore, we synthesize an enter notify event manually.
+   */
+  if (!initialPositionKnown)
+    {
+      initialPositionKnown = YES;
+
+      if (NSPointInRect ([NSEvent mouseLocation], [self frame]))
+        {
+          GdkMacosBaseView *view = (GdkMacosBaseView *)[self contentView];
+          NSEvent *event;
+
+          event = [NSEvent enterExitEventWithType: NSEventTypeMouseEntered
+                                         location: [self mouseLocationOutsideOfEventStream]
+                                    modifierFlags: 0
+                                        timestamp: [[NSApp currentEvent] timestamp]
+                                     windowNumber: [self windowNumber]
+                                          context: NULL
+                                      eventNumber: 0
+                                   trackingNumber: (NSInteger)[view trackingArea]
+                                         userData: nil];
+
+          [NSApp postEvent:event atStart:NO];
+        }
+    }
+}
+
+-(void)windowDidUnmaximize
+{
+  NSWindowStyleMask style_mask = [self styleMask];
+
+  gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), GDK_SURFACE_STATE_MAXIMIZED, 0);
+
+  /* If we are using CSD, then we transitioned to an opaque
+   * window while we were maximized. Now we need to drop that
+   * as we are leaving maximized state.
+   */
+  if ((style_mask & NSWindowStyleMaskTitled) == 0 && [self isOpaque])
+    [self setOpaque:NO];
+}
+
+-(void)windowDidMove:(NSNotification *)aNotification
+{
+  GdkSurface *surface = GDK_SURFACE (gdk_surface);
+  gboolean maximized = (surface->state & GDK_SURFACE_STATE_MAXIMIZED) != 0;
+
+  /* In case the window is changed when maximized remove the maximized state */
+  if (maximized && !inMaximizeTransition && !NSEqualRects (lastMaximizedFrame, [self frame]))
+    [self windowDidUnmaximize];
+
+  _gdk_macos_surface_update_position (gdk_surface);
+  _gdk_macos_surface_reposition_children (gdk_surface);
+
+  [self checkSendEnterNotify];
+}
+
+-(void)windowDidResize:(NSNotification *)aNotification
+{
+  NSRect content_rect;
+  GdkSurface *surface;
+  GdkDisplay *display;
+  GdkEvent *event;
+  gboolean maximized;
+  GList *node;
+
+  surface = GDK_SURFACE (gdk_surface);
+  display = gdk_surface_get_display (surface);
+
+  content_rect = [self contentRectForFrameRect:[self frame]];
+  maximized = (surface->state & GDK_SURFACE_STATE_MAXIMIZED) != 0;
+
+  /* see same in windowDidMove */
+  if (maximized && !inMaximizeTransition && !NSEqualRects (lastMaximizedFrame, [self frame]))
+    [self windowDidUnmaximize];
+
+  surface->width = content_rect.size.width;
+  surface->height = content_rect.size.height;
+
+  /* Certain resize operations (e.g. going fullscreen), also move the
+   * origin of the window.
+   */
+  _gdk_macos_surface_update_position (GDK_MACOS_SURFACE (surface));
+
+  [[self contentView] setFrame:NSMakeRect (0, 0, surface->width, surface->height)];
+
+  _gdk_surface_update_size (surface);
+
+  /* Synthesize a configure event */
+  event = gdk_configure_event_new (surface,
+                                   content_rect.size.width,
+                                   content_rect.size.height);
+  node = _gdk_event_queue_append (display, event);
+  _gdk_windowing_got_event (display, node, event,
+                            _gdk_display_get_next_serial (display));
+
+  _gdk_macos_surface_reposition_children (gdk_surface);
+
+  [self checkSendEnterNotify];
+}
+
+-(id)initWithContentRect:(NSRect)contentRect
+               styleMask:(NSWindowStyleMask)styleMask
+                 backing:(NSBackingStoreType)backingType
+                   defer:(BOOL)flag
+                  screen:(NSScreen *)screen
+{
+  GdkMacosCairoView *view;
+
+  self = [super initWithContentRect:contentRect
+                               styleMask:styleMask
+                                 backing:backingType
+                                   defer:flag
+                             screen:screen];
+
+  [self setAcceptsMouseMovedEvents:YES];
+  [self setDelegate:(id<NSWindowDelegate>)self];
+  [self setReleasedWhenClosed:YES];
+
+  view = [[GdkMacosCairoView alloc] initWithFrame:contentRect];
+  [self setContentView:view];
+  [view release];
+
+  return self;
+}
+
+-(BOOL)canBecomeMainWindow
+{
+  return GDK_IS_TOPLEVEL (gdk_surface);
+}
+
+-(BOOL)canBecomeKeyWindow
+{
+  return GDK_IS_TOPLEVEL (gdk_surface);
+}
+
+-(void)showAndMakeKey:(BOOL)makeKey
+{
+  inShowOrHide = YES;
+
+  if (makeKey && [self canBecomeKeyWindow])
+    [self makeKeyAndOrderFront:nil];
+  else
+    [self orderFront:nil];
+
+  inShowOrHide = NO;
+
+  [self checkSendEnterNotify];
+}
+
+-(void)hide
+{
+  inShowOrHide = YES;
+  [self orderOut:nil];
+  inShowOrHide = NO;
+
+  initialPositionKnown = NO;
+}
+
+-(BOOL)trackManualMove
+{
+  NSRect windowFrame;
+  NSPoint currentLocation;
+  GdkMonitor *monitor;
+  GdkRectangle geometry;
+  GdkRectangle workarea;
+  int shadow_top = 0;
+  int shadow_left = 0;
+  int shadow_right = 0;
+  int shadow_bottom = 0;
+  GdkRectangle window_gdk;
+  GdkPoint pointer_position;
+  GdkPoint new_origin;
+
+  if (!inManualMove)
+    return NO;
+
+  /* Get our shadow so we can adjust the window position sans-shadow */
+  _gdk_macos_surface_get_shadow (gdk_surface,
+                                 &shadow_top,
+                                 &shadow_right,
+                                 &shadow_bottom,
+                                 &shadow_left);
+
+  windowFrame = [self frame];
+  currentLocation = [NSEvent mouseLocation];
+
+  /* Update the snapping geometry to match the current monitor */
+  monitor = _gdk_macos_display_get_monitor_at_display_coords ([self gdkDisplay],
+                                                              currentLocation.x,
+                                                              currentLocation.y);
+  gdk_monitor_get_geometry (monitor, &geometry);
+  gdk_monitor_get_workarea (monitor, &workarea);
+  _edge_snapping_set_monitor (&self->snapping, &geometry, &workarea);
+
+  /* Convert origins to GDK coordinates */
+  _gdk_macos_display_from_display_coords ([self gdkDisplay],
+                                          currentLocation.x,
+                                          currentLocation.y,
+                                          &pointer_position.x,
+                                          &pointer_position.y);
+  _gdk_macos_display_from_display_coords ([self gdkDisplay],
+                                          windowFrame.origin.x,
+                                          windowFrame.origin.y + windowFrame.size.height,
+                                          &window_gdk.x,
+                                          &window_gdk.y);
+  window_gdk.width = windowFrame.size.width;
+  window_gdk.height = windowFrame.size.height;
+
+  /* Subtract our shadowin from the window */
+  window_gdk.x += shadow_left;
+  window_gdk.y += shadow_top;
+  window_gdk.width = window_gdk.width - shadow_left - shadow_right;
+  window_gdk.height = window_gdk.height - shadow_top - shadow_bottom;
+
+  /* Now place things on the monitor */
+  _edge_snapping_motion (&self->snapping, &pointer_position, &window_gdk);
+
+  /* And add our shadow back to the frame */
+  window_gdk.x -= shadow_left;
+  window_gdk.y -= shadow_top;
+  window_gdk.width += shadow_left + shadow_right;
+  window_gdk.height += shadow_top + shadow_bottom;
+
+  /* Convert to quartz coordiantes */
+  _gdk_macos_display_to_display_coords ([self gdkDisplay],
+                                        window_gdk.x,
+                                        window_gdk.y + window_gdk.height,
+                                        &new_origin.x, &new_origin.y);
+  windowFrame.origin.x = new_origin.x;
+  windowFrame.origin.y = new_origin.y;
+
+  /* And now apply the frame to the window */
+  [self setFrameOrigin:NSMakePoint(new_origin.x, new_origin.y)];
+
+  return YES;
+}
+
+/* Used by gdkmacosdisplay-translate.c to decide if our sendEvent() handler
+ * above will see the event or if it will be subjected to standard processing
+ * by GDK.
+*/
+-(BOOL)isInManualResizeOrMove
+{
+  return inManualResize || inManualMove;
+}
+
+-(void)beginManualMove
+{
+  NSPoint initialMoveLocation;
+  GdkPoint point;
+  GdkMonitor *monitor;
+  GdkRectangle geometry;
+  GdkRectangle area;
+  GdkRectangle workarea;
+
+  if (inMove || inManualMove || inManualResize)
+    return;
+
+  inManualMove = YES;
+
+  monitor = _gdk_macos_surface_get_best_monitor ([self gdkSurface]);
+  gdk_monitor_get_geometry (monitor, &geometry);
+  gdk_monitor_get_workarea (monitor, &workarea);
+
+  initialMoveLocation = [NSEvent mouseLocation];
+
+  _gdk_macos_display_from_display_coords ([self gdkDisplay],
+                                          initialMoveLocation.x,
+                                          initialMoveLocation.y,
+                                          &point.x,
+                                          &point.y);
+
+  area.x = gdk_surface->root_x;
+  area.y = gdk_surface->root_y;
+  area.width = GDK_SURFACE (gdk_surface)->width;
+  area.height = GDK_SURFACE (gdk_surface)->height;
+
+  _edge_snapping_init (&self->snapping,
+                       &geometry,
+                       &workarea,
+                       &point,
+                       &area);
+}
+
+-(BOOL)trackManualResize
+{
+  NSPoint mouse_location;
+  NSRect new_frame;
+  float mdx, mdy, dw, dh, dx, dy;
+  NSSize min_size;
+
+  if (!inManualResize || inTrackManualResize)
+    return NO;
+
+  inTrackManualResize = YES;
+
+  mouse_location = [self convertPointToScreen:[self mouseLocationOutsideOfEventStream]];
+  mdx = initialResizeLocation.x - mouse_location.x;
+  mdy = initialResizeLocation.y - mouse_location.y;
+
+  /* Set how a mouse location delta translates to changes in width,
+   * height and position.
+   */
+  dw = dh = dx = dy = 0.0;
+  if (resizeEdge == GDK_SURFACE_EDGE_EAST ||
+      resizeEdge == GDK_SURFACE_EDGE_NORTH_EAST ||
+      resizeEdge == GDK_SURFACE_EDGE_SOUTH_EAST)
+    {
+      dw = -1.0;
+    }
+  if (resizeEdge == GDK_SURFACE_EDGE_NORTH ||
+      resizeEdge == GDK_SURFACE_EDGE_NORTH_WEST ||
+      resizeEdge == GDK_SURFACE_EDGE_NORTH_EAST)
+    {
+      dh = -1.0;
+    }
+  if (resizeEdge == GDK_SURFACE_EDGE_SOUTH ||
+      resizeEdge == GDK_SURFACE_EDGE_SOUTH_WEST ||
+      resizeEdge == GDK_SURFACE_EDGE_SOUTH_EAST)
+    {
+      dh = 1.0;
+      dy = -1.0;
+    }
+  if (resizeEdge == GDK_SURFACE_EDGE_WEST ||
+      resizeEdge == GDK_SURFACE_EDGE_NORTH_WEST ||
+      resizeEdge == GDK_SURFACE_EDGE_SOUTH_WEST)
+    {
+      dw = 1.0;
+      dx = -1.0;
+    }
+
+  /* Apply changes to the frame captured when we started resizing */
+  new_frame = initialResizeFrame;
+  new_frame.origin.x += mdx * dx;
+  new_frame.origin.y += mdy * dy;
+  new_frame.size.width += mdx * dw;
+  new_frame.size.height += mdy * dh;
+
+  /* In case the resulting window would be too small reduce the
+   * change to both size and position.
+   */
+  min_size = [self contentMinSize];
+
+  if (new_frame.size.width < min_size.width)
+    {
+      if (dx)
+        new_frame.origin.x -= min_size.width - new_frame.size.width;
+      new_frame.size.width = min_size.width;
+    }
+
+  if (new_frame.size.height < min_size.height)
+    {
+      if (dy)
+        new_frame.origin.y -= min_size.height - new_frame.size.height;
+      new_frame.size.height = min_size.height;
+    }
+
+  /* We could also apply aspect ratio:
+     new_frame.size.height = new_frame.size.width / [self aspectRatio].width * [self aspectRatio].height;
+  */
+
+  [self setFrame:new_frame display:YES];
+
+  /* Let the resizing be handled by GTK+. */
+  if (g_main_context_pending (NULL))
+    g_main_context_iteration (NULL, FALSE);
+
+  inTrackManualResize = NO;
+
+  return YES;
+}
+
+-(void)beginManualResize:(GdkSurfaceEdge)edge
+{
+  if (inMove || inManualMove || inManualResize)
+    return;
+
+  inManualResize = YES;
+  resizeEdge = edge;
+
+  initialResizeFrame = [self frame];
+  initialResizeLocation = [self convertPointToScreen:[self mouseLocationOutsideOfEventStream]];
+}
+
+-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+{
+  return NSDragOperationNone;
+}
+
+-(void)draggingEnded:(id <NSDraggingInfo>)sender
+{
+}
+
+-(void)draggingExited:(id <NSDraggingInfo>)sender
+{
+}
+
+-(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
+{
+  return NSDragOperationNone;
+}
+
+-(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
+{
+  return YES;
+}
+
+-(BOOL)wantsPeriodicDraggingUpdates
+{
+  return NO;
+}
+
+-(void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation
+{
+}
+
+-(void)setStyleMask:(NSWindowStyleMask)styleMask
+{
+  gboolean was_fullscreen;
+  gboolean is_fullscreen;
+  gboolean was_opaque;
+  gboolean is_opaque;
+
+  was_fullscreen = (([self styleMask] & NSWindowStyleMaskFullScreen) != 0);
+  was_opaque = (([self styleMask] & NSWindowStyleMaskTitled) != 0);
+
+  [super setStyleMask:styleMask];
+
+  is_fullscreen = (([self styleMask] & NSWindowStyleMaskFullScreen) != 0);
+  is_opaque = (([self styleMask] & NSWindowStyleMaskTitled) != 0);
+
+  if (was_fullscreen != is_fullscreen)
+    _gdk_macos_surface_update_fullscreen_state (gdk_surface);
+
+  if (was_opaque != is_opaque)
+    {
+      [self setOpaque:is_opaque];
+
+      if (!is_opaque)
+        [self setBackgroundColor:[NSColor clearColor]];
+    }
+}
+
+-(NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
+{
+  GdkMacosSurface *surface = gdk_surface;
+  NSRect rect;
+  gint shadow_top;
+
+  /* Allow the window to move up "shadow_top" more than normally allowed
+   * by the default impl. This makes it possible to move windows with
+   * client side shadow right up to the screen's menu bar. */
+  _gdk_macos_surface_get_shadow (surface, &shadow_top, NULL, NULL, NULL);
+  rect = [super constrainFrameRect:frameRect toScreen:screen];
+  if (frameRect.origin.y > rect.origin.y)
+    rect.origin.y = MIN (frameRect.origin.y, rect.origin.y + shadow_top);
+
+  return rect;
+}
+
+-(NSRect)windowWillUseStandardFrame:(NSWindow *)nsWindow
+                       defaultFrame:(NSRect)newFrame
+{
+  NSRect screenFrame = [[self screen] visibleFrame];
+  GdkMacosSurface *surface = gdk_surface;
+  gboolean maximized = GDK_SURFACE (surface)->state & GDK_SURFACE_STATE_MAXIMIZED;
+
+  if (!maximized)
+    return screenFrame;
+  else
+    return lastUnmaximizedFrame;
+}
+
+-(BOOL)windowShouldZoom:(NSWindow *)nsWindow
+                toFrame:(NSRect)newFrame
+{
+  GdkMacosSurface *surface = gdk_surface;
+  GdkSurfaceState state = GDK_SURFACE (surface)->state;
+
+  if (state & GDK_SURFACE_STATE_MAXIMIZED)
+    {
+      lastMaximizedFrame = newFrame;
+      [self windowDidUnmaximize];
+    }
+  else
+    {
+      lastUnmaximizedFrame = [nsWindow frame];
+      gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), 0, GDK_SURFACE_STATE_MAXIMIZED);
+    }
+
+  inMaximizeTransition = YES;
+
+  return YES;
+}
+
+-(void)windowDidEndLiveResize:(NSNotification *)aNotification
+{
+  gboolean maximized = GDK_SURFACE (gdk_surface)->state & GDK_SURFACE_STATE_MAXIMIZED;
+
+  inMaximizeTransition = NO;
+
+  /* Even if this is CSD, we want to be opaque while maximized
+   * to speed up compositing by allowing the display server to
+   * avoid costly blends.
+   */
+  if (maximized)
+    [self setOpaque:YES];
+}
+
+-(NSSize)window:(NSWindow *)window willUseFullScreenContentSize:(NSSize)proposedSize
+{
+  return [[window screen] frame].size;
+}
+
+-(void)windowWillEnterFullScreen:(NSNotification *)aNotification
+{
+  lastUnfullscreenFrame = [self frame];
+}
+
+-(void)windowWillExitFullScreen:(NSNotification *)aNotification
+{
+  [self setFrame:lastUnfullscreenFrame display:YES];
+}
+
+-(void)windowDidExitFullScreen:(NSNotification *)aNotification
+{
+}
+
+-(void)windowDidChangeScreen:(NSNotification *)aNotification
+{
+  _gdk_macos_surface_monitor_changed (gdk_surface);
+}
+
+-(void)setGdkSurface:(GdkMacosSurface *)surface
+{
+  self->gdk_surface = surface;
+}
+
+-(void)setDecorated:(BOOL)decorated
+{
+  NSWindowStyleMask style_mask = [self styleMask];
+
+  [self setHasShadow:decorated];
+
+  if (decorated)
+    style_mask |= NSWindowStyleMaskTitled;
+  else
+    style_mask &= ~NSWindowStyleMaskTitled;
+
+  [self setStyleMask:style_mask];
+}
+
+-(GdkMacosSurface *)gdkSurface
+{
+  return self->gdk_surface;
+}
+
+-(GdkMacosDisplay *)gdkDisplay
+{
+  return GDK_MACOS_DISPLAY (GDK_SURFACE (self->gdk_surface)->display);
+}
+
+-(BOOL)movableByWindowBackground
+{
+  return NO;
+}
+
+@end
diff --git a/gdk/macos/GdkMacosWindow.h b/gdk/macos/GdkMacosWindow.h
new file mode 100644 (file)
index 0000000..61f546a
--- /dev/null
@@ -0,0 +1,70 @@
+/* GdkMacosWindow.h
+ *
+ * Copyright © 2020 Red Hat, Inc.
+ * Copyright © 2005-2007 Imendio AB
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#import <AppKit/AppKit.h>
+#import <Foundation/Foundation.h>
+
+#include <gdk/gdk.h>
+
+#include "gdkmacosdisplay.h"
+#include "gdkmacossurface.h"
+#include "edgesnapping.h"
+
+#define GDK_IS_MACOS_WINDOW(obj) ([obj isKindOfClass:[GdkMacosWindow class]])
+
+@interface GdkMacosWindow : NSWindow {
+  GdkMacosSurface *gdk_surface;
+
+  BOOL             inMove;
+  BOOL             inShowOrHide;
+  BOOL             initialPositionKnown;
+
+  /* Manually triggered move/resize (not by the window manager) */
+  BOOL             inManualMove;
+  BOOL             inManualResize;
+  BOOL             inTrackManualResize;
+  NSPoint          initialResizeLocation;
+  NSRect           initialResizeFrame;
+  GdkSurfaceEdge   resizeEdge;
+
+  EdgeSnapping     snapping;
+
+  NSRect           lastUnmaximizedFrame;
+  NSRect           lastMaximizedFrame;
+  NSRect           lastUnfullscreenFrame;
+  BOOL             inMaximizeTransition;
+}
+
+-(void)beginManualMove;
+-(void)beginManualResize:(GdkSurfaceEdge)edge;
+-(void)hide;
+-(BOOL)isInManualResizeOrMove;
+-(BOOL)isInMove;
+-(GdkMacosDisplay *)gdkDisplay;
+-(GdkMacosSurface *)gdkSurface;
+-(void)setGdkSurface:(GdkMacosSurface *)surface;
+-(void)setStyleMask:(NSWindowStyleMask)styleMask;
+-(void)showAndMakeKey:(BOOL)makeKey;
+-(BOOL)trackManualMove;
+-(BOOL)trackManualResize;
+-(void)setDecorated:(BOOL)decorated;
+
+@end
diff --git a/gdk/macos/edgesnapping.c b/gdk/macos/edgesnapping.c
new file mode 100644 (file)
index 0000000..bf93472
--- /dev/null
@@ -0,0 +1,229 @@
+/* edgesnapping.c
+ *
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "gdkrectangle.h"
+#include "edgesnapping.h"
+
+#define LEAVE_THRESHOLD 3.0
+#define ENTER_THRESHOLD 2.0
+
+#define X1(r) ((r)->x)
+#define X2(r) ((r)->x + (r)->width)
+#define Y1(r) ((r)->y)
+#define Y2(r) ((r)->y + (r)->height)
+
+void
+_edge_snapping_init (EdgeSnapping       *self,
+                     const GdkRectangle *geometry,
+                     const GdkRectangle *workarea,
+                     const GdkPoint     *pointer_position,
+                     const GdkRectangle *window)
+{
+  g_assert (self != NULL);
+  g_assert (geometry != NULL);
+  g_assert (workarea != NULL);
+  g_assert (pointer_position != NULL);
+
+  self->geometry = *geometry;
+  self->workarea = *workarea;
+  self->last_pointer_position = *pointer_position;
+  self->pointer_offset_in_window.x = pointer_position->x - window->x;
+  self->pointer_offset_in_window.y = pointer_position->y - window->y;
+}
+
+static void
+edge_snapping_constrain_left (EdgeSnapping       *self,
+                              int                 change,
+                              const GdkRectangle *geometry,
+                              GdkRectangle       *window)
+{
+  if (change < 0)
+    {
+      if (X1 (window) < X1 (geometry) &&
+          X1 (window) > X1 (geometry) - LEAVE_THRESHOLD &&
+          ABS (change) < LEAVE_THRESHOLD)
+        window->x = geometry->x;
+    }
+
+  /* We don't constrain when returning from left edge */
+}
+
+static void
+edge_snapping_constrain_right (EdgeSnapping       *self,
+                               int                 change,
+                               const GdkRectangle *geometry,
+                               GdkRectangle       *window)
+{
+  if (change > 0)
+    {
+      if (X2 (window) > X2 (geometry) &&
+          X2 (window) < X2 (geometry) + LEAVE_THRESHOLD &&
+          ABS (change) < LEAVE_THRESHOLD)
+        window->x = X2 (geometry) - window->width;
+    }
+
+  /* We don't constrain when returning from right edge */
+}
+
+static void
+edge_snapping_constrain_top (EdgeSnapping       *self,
+                             int                 change,
+                             const GdkRectangle *geometry,
+                             GdkRectangle       *window)
+{
+  if (change < 0)
+    {
+      if (Y1 (window) < Y1 (geometry))
+        window->y = geometry->y;
+    }
+
+  /* We don't constrain when returning from top edge */
+}
+
+static void
+edge_snapping_constrain_bottom (EdgeSnapping       *self,
+                                int                 change,
+                                const GdkRectangle *geometry,
+                                GdkRectangle       *window)
+{
+  if (change > 0)
+    {
+      if (Y2 (window) > Y2 (geometry) &&
+          Y2 (window) < Y2 (geometry) + LEAVE_THRESHOLD &&
+          ABS (change) < LEAVE_THRESHOLD)
+        window->y = Y2 (geometry) - window->height;
+    }
+  else if (change < 0)
+    {
+      if (Y2 (window) < Y2 (geometry) &&
+          Y2 (window) > Y2 (geometry) - ENTER_THRESHOLD &&
+          ABS (change) < ENTER_THRESHOLD)
+        window->y = Y2 (geometry) - window->height;
+    }
+
+}
+
+static void
+edge_snapping_constrain_horizontal (EdgeSnapping       *self,
+                                    int                 change,
+                                    const GdkRectangle *geometry,
+                                    GdkRectangle       *window)
+{
+  g_assert (self != NULL);
+  g_assert (geometry != NULL);
+  g_assert (window != NULL);
+  g_assert (change != 0);
+
+  if (ABS (X1 (geometry) - X1 (window)) < ABS (X2 (geometry)) - ABS (X2 (window)))
+    edge_snapping_constrain_left (self, change, geometry, window);
+  else
+    edge_snapping_constrain_right (self, change, geometry, window);
+}
+
+static void
+edge_snapping_constrain_vertical (EdgeSnapping       *self,
+                                  int                 change,
+                                  const GdkRectangle *geometry,
+                                  GdkRectangle       *window,
+                                  gboolean            bottom_only)
+{
+  g_assert (self != NULL);
+  g_assert (geometry != NULL);
+  g_assert (window != NULL);
+  g_assert (change != 0);
+
+  if (!bottom_only &&
+      ABS (Y1 (geometry) - Y1 (window)) < ABS (Y2 (geometry)) - ABS (Y2 (window)))
+    edge_snapping_constrain_top (self, change, geometry, window);
+  else
+    edge_snapping_constrain_bottom (self, change, geometry, window);
+}
+
+void
+_edge_snapping_motion (EdgeSnapping   *self,
+                       const GdkPoint *pointer_position,
+                       GdkRectangle   *window)
+{
+  GdkRectangle new_window;
+  GdkRectangle overlap;
+  GdkPoint change;
+
+  g_assert (self != NULL);
+  g_assert (pointer_position != NULL);
+
+  change.x = pointer_position->x - self->last_pointer_position.x;
+  change.y = pointer_position->y - self->last_pointer_position.y;
+
+  self->last_pointer_position = *pointer_position;
+
+  window->x += change.x;
+  window->y += change.y;
+
+  new_window = *window;
+
+  /* First constrain horizontal */
+  if (change.x)
+    {
+      edge_snapping_constrain_horizontal (self, change.x, &self->workarea, &new_window);
+      if (gdk_rectangle_equal (&new_window, window))
+        edge_snapping_constrain_horizontal (self, change.x, &self->geometry, &new_window);
+    }
+
+  /* Now constrain veritcally */
+  if (change.y)
+    {
+      edge_snapping_constrain_vertical (self, change.y, &self->workarea, &new_window, FALSE);
+      if (new_window.y == window->y)
+        edge_snapping_constrain_vertical (self, change.y, &self->geometry, &new_window, TRUE);
+    }
+
+  /* If the window is not placed in the monitor at all, then we need to
+   * just move the window onto the new screen using the original offset
+   * of the pointer within the window.
+   */
+  if (!gdk_rectangle_intersect (&self->geometry, &new_window, &overlap))
+    {
+      new_window.x = pointer_position->x - self->pointer_offset_in_window.x;
+      new_window.y = pointer_position->y - self->pointer_offset_in_window.y;
+    }
+
+  /* And finally make sure we aren't underneath the top bar of the
+   * particular monitor.
+   */
+  if (Y1 (&new_window) < Y1 (&self->workarea))
+    new_window.y = self->workarea.y;
+
+  *window = new_window;
+}
+
+void
+_edge_snapping_set_monitor (EdgeSnapping       *self,
+                            const GdkRectangle *geometry,
+                            const GdkRectangle *workarea)
+{
+  g_assert (self != NULL);
+  g_assert (geometry != NULL);
+  g_assert (workarea != NULL);
+
+  self->geometry = *geometry;
+  self->workarea = *workarea;
+}
diff --git a/gdk/macos/edgesnapping.h b/gdk/macos/edgesnapping.h
new file mode 100644 (file)
index 0000000..8769ea7
--- /dev/null
@@ -0,0 +1,50 @@
+/* edgesnapping.h
+ *
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __EDGE_SNAPPING_H__
+#define __EDGE_SNAPPING_H__
+
+#include "gdktypes.h"
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+  GdkRectangle geometry;
+  GdkRectangle workarea;
+  GdkPoint     last_pointer_position;
+  GdkPoint     pointer_offset_in_window;
+} EdgeSnapping;
+
+void _edge_snapping_init        (EdgeSnapping       *self,
+                                 const GdkRectangle *geometry,
+                                 const GdkRectangle *workarea,
+                                 const GdkPoint     *pointer_position,
+                                 const GdkRectangle *window);
+void _edge_snapping_motion      (EdgeSnapping       *self,
+                                 const GdkPoint     *pointer_position,
+                                 GdkRectangle       *window);
+void _edge_snapping_set_monitor (EdgeSnapping       *self,
+                                 const GdkRectangle *geometry,
+                                 const GdkRectangle *workarea);
+
+G_END_DECLS
+
+#endif /* __EDGE_SNAPPING_H__ */
diff --git a/gdk/macos/gdkdisplaylinksource.c b/gdk/macos/gdkdisplaylinksource.c
new file mode 100644 (file)
index 0000000..ba8731d
--- /dev/null
@@ -0,0 +1,254 @@
+/* gdkdisplaylinksource.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian@hergert.me>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *   Christian Hergert <christian@hergert.me>
+ */
+
+#include "config.h"
+
+#include <AppKit/AppKit.h>
+#include <mach/mach_time.h>
+
+#include "gdkdisplaylinksource.h"
+
+#include "gdkmacoseventsource-private.h"
+
+static gint64 host_to_frame_clock_time (gint64 host_time);
+
+static gboolean
+gdk_display_link_source_prepare (GSource *source,
+                                 gint    *timeout_)
+{
+  GdkDisplayLinkSource *impl = (GdkDisplayLinkSource *)source;
+  gint64 now;
+
+  now = g_source_get_time (source);
+
+  if (now < impl->presentation_time)
+    *timeout_ = (impl->presentation_time - now) / 1000L;
+  else
+    *timeout_ = -1;
+
+  return impl->needs_dispatch;
+}
+
+static gboolean
+gdk_display_link_source_check (GSource *source)
+{
+  GdkDisplayLinkSource *impl = (GdkDisplayLinkSource *)source;
+  return impl->needs_dispatch;
+}
+
+static gboolean
+gdk_display_link_source_dispatch (GSource     *source,
+                                  GSourceFunc  callback,
+                                  gpointer     user_data)
+{
+  GdkDisplayLinkSource *impl = (GdkDisplayLinkSource *)source;
+  gboolean ret = G_SOURCE_CONTINUE;
+
+  impl->needs_dispatch = FALSE;
+
+  if (callback != NULL)
+    ret = callback (user_data);
+
+  return ret;
+}
+
+static void
+gdk_display_link_source_finalize (GSource *source)
+{
+  GdkDisplayLinkSource *impl = (GdkDisplayLinkSource *)source;
+
+  CVDisplayLinkStop (impl->display_link);
+  CVDisplayLinkRelease (impl->display_link);
+}
+
+static GSourceFuncs gdk_display_link_source_funcs = {
+  gdk_display_link_source_prepare,
+  gdk_display_link_source_check,
+  gdk_display_link_source_dispatch,
+  gdk_display_link_source_finalize
+};
+
+void
+gdk_display_link_source_pause (GdkDisplayLinkSource *source)
+{
+  CVDisplayLinkStop (source->display_link);
+}
+
+void
+gdk_display_link_source_unpause (GdkDisplayLinkSource *source)
+{
+  CVDisplayLinkStart (source->display_link);
+}
+
+static CVReturn
+gdk_display_link_source_frame_cb (CVDisplayLinkRef   display_link,
+                                  const CVTimeStamp *inNow,
+                                  const CVTimeStamp *inOutputTime,
+                                  CVOptionFlags      flagsIn,
+                                  CVOptionFlags     *flagsOut,
+                                  void              *user_data)
+{
+  GdkDisplayLinkSource *impl = user_data;
+  gint64 presentation_time;
+  gboolean needs_wakeup;
+
+  needs_wakeup = !g_atomic_int_get (&impl->needs_dispatch);
+
+  presentation_time = host_to_frame_clock_time (inOutputTime->hostTime);
+
+  impl->presentation_time = presentation_time;
+  impl->needs_dispatch = TRUE;
+
+  if (needs_wakeup)
+    {
+      NSEvent *event;
+
+      /* Post a message so we'll break out of the message loop.
+       *
+       * We don't use g_main_context_wakeup() here because that
+       * would result in sending a message to the pipe(2) fd in
+       * the select thread which would then send this message as
+       * well. Lots of extra work.
+       */
+      event = [NSEvent otherEventWithType: NSEventTypeApplicationDefined
+                                 location: NSZeroPoint
+                            modifierFlags: 0
+                                timestamp: 0
+                             windowNumber: 0
+                                  context: nil
+                                  subtype: GDK_MACOS_EVENT_SUBTYPE_EVENTLOOP
+                                    data1: 0
+                                    data2: 0];
+
+      [NSApp postEvent:event atStart:YES];
+    }
+
+  return kCVReturnSuccess;
+}
+
+/**
+ * gdk_display_link_source_new:
+ *
+ * Creates a new #GSource that will activate the dispatch function upon
+ * notification from a CVDisplayLink that a new frame should be drawn.
+ *
+ * Effort is made to keep the transition from the high-priority
+ * CVDisplayLink thread into this GSource lightweight. However, this is
+ * somewhat non-ideal since the best case would be to do the drawing
+ * from the high-priority thread.
+ *
+ * Returns: (transfer full): A newly created #GSource.
+ */
+GSource *
+gdk_display_link_source_new (void)
+{
+  GdkDisplayLinkSource *impl;
+  GSource *source;
+  CVReturn ret;
+  double period;
+
+  source = g_source_new (&gdk_display_link_source_funcs, sizeof *impl);
+  impl = (GdkDisplayLinkSource *)source;
+
+  /*
+   * Create our link based on currently connected displays.
+   * If there are multiple displays, this will be something that tries
+   * to work for all of them. In the future, we may want to explore multiple
+   * links based on the connected displays.
+   */
+  ret = CVDisplayLinkCreateWithActiveCGDisplays (&impl->display_link);
+  if (ret != kCVReturnSuccess)
+    {
+      g_warning ("Failed to initialize CVDisplayLink!");
+      return source;
+    }
+
+  /*
+   * Determine our nominal period between frames.
+   */
+  period = CVDisplayLinkGetActualOutputVideoRefreshPeriod (impl->display_link);
+  if (period == 0.0)
+    period = 1.0 / 60.0;
+  impl->refresh_interval = period * 1000000L;
+  impl->refresh_rate = 1.0 / period * 1000L;
+
+  /*
+   * Wire up our callback to be executed within the high-priority thread.
+   */
+  CVDisplayLinkSetOutputCallback (impl->display_link,
+                                  gdk_display_link_source_frame_cb,
+                                  source);
+
+  g_source_set_name (source, "[gdk] quartz frame clock");
+
+  return source;
+}
+
+static gint64
+host_to_frame_clock_time (gint64 host_time)
+{
+  static mach_timebase_info_data_t timebase_info;
+
+  /*
+   * NOTE:
+   *
+   * This code is taken from GLib to match g_get_monotonic_time().
+   */
+  if (G_UNLIKELY (timebase_info.denom == 0))
+    {
+      /* This is a fraction that we must use to scale
+       * mach_absolute_time() by in order to reach nanoseconds.
+       *
+       * We've only ever observed this to be 1/1, but maybe it could be
+       * 1000/1 if mach time is microseconds already, or 1/1000 if
+       * picoseconds.  Try to deal nicely with that.
+       */
+      mach_timebase_info (&timebase_info);
+
+      /* We actually want microseconds... */
+      if (timebase_info.numer % 1000 == 0)
+        timebase_info.numer /= 1000;
+      else
+        timebase_info.denom *= 1000;
+
+      /* We want to make the numer 1 to avoid having to multiply... */
+      if (timebase_info.denom % timebase_info.numer == 0)
+        {
+          timebase_info.denom /= timebase_info.numer;
+          timebase_info.numer = 1;
+        }
+      else
+        {
+          /* We could just multiply by timebase_info.numer below, but why
+           * bother for a case that may never actually exist...
+           *
+           * Plus -- performing the multiplication would risk integer
+           * overflow.  If we ever actually end up in this situation, we
+           * should more carefully evaluate the correct course of action.
+           */
+          mach_timebase_info (&timebase_info); /* Get a fresh copy for a better message */
+          g_error ("Got weird mach timebase info of %d/%d.  Please file a bug against GLib.",
+                   timebase_info.numer, timebase_info.denom);
+        }
+    }
+
+  return host_time / timebase_info.denom;
+}
diff --git a/gdk/macos/gdkdisplaylinksource.h b/gdk/macos/gdkdisplaylinksource.h
new file mode 100644 (file)
index 0000000..ed769b5
--- /dev/null
@@ -0,0 +1,49 @@
+/* gdkdisplaylinksource.h
+ *
+ * Copyright (C) 2015 Christian Hergert <christian@hergert.me>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *   Christian Hergert <christian@hergert.me>
+ */
+
+#ifndef GDK_DISPLAY_LINK_SOURCE_H
+#define GDK_DISPLAY_LINK_SOURCE_H
+
+#include <glib.h>
+
+#include <QuartzCore/QuartzCore.h>
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+  GSource          source;
+
+  CVDisplayLinkRef display_link;
+  gint64           refresh_interval;
+  guint            refresh_rate;
+
+  volatile gint64  presentation_time;
+  volatile guint   needs_dispatch;
+} GdkDisplayLinkSource;
+
+GSource *gdk_display_link_source_new     (void);
+void     gdk_display_link_source_pause   (GdkDisplayLinkSource *source);
+void     gdk_display_link_source_unpause (GdkDisplayLinkSource *source);
+
+G_END_DECLS
+
+#endif /* GDK_DISPLAY_LINK_SOURCE_H */
diff --git a/gdk/macos/gdkmacos.h b/gdk/macos/gdkmacos.h
new file mode 100644 (file)
index 0000000..7d7d348
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_H__
+#define __GDK_MACOS_H__
+
+#include <gdk/gdk.h>
+
+#include "gdkmacosdevice.h"
+#include "gdkmacosdisplay.h"
+#include "gdkmacosglcontext.h"
+#include "gdkmacoskeymap.h"
+#include "gdkmacosmonitor.h"
+#include "gdkmacossurface.h"
+
+#endif /* __GDK_MACOS_H__ */
diff --git a/gdk/macos/gdkmacoscairocontext-private.h b/gdk/macos/gdkmacoscairocontext-private.h
new file mode 100644 (file)
index 0000000..1afede8
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_CAIRO_CONTEXT_PRIVATE_H__
+#define __GDK_MACOS_CAIRO_CONTEXT_PRIVATE_H__
+
+#include "gdkcairocontextprivate.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GdkMacosCairoContext      GdkMacosCairoContext;
+typedef struct _GdkMacosCairoContextClass GdkMacosCairoContextClass;
+
+#define GDK_TYPE_MACOS_CAIRO_CONTEXT       (_gdk_macos_cairo_context_get_type())
+#define GDK_MACOS_CAIRO_CONTEXT(object)    (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_CAIRO_CONTEXT, GdkMacosCairoContext))
+#define GDK_IS_MACOS_CAIRO_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_CAIRO_CONTEXT))
+
+GType _gdk_macos_cairo_context_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_CAIRO_CONTEXT_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacoscairocontext.c b/gdk/macos/gdkmacoscairocontext.c
new file mode 100644 (file)
index 0000000..e70d2bf
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright © 2016 Benjamin Otte
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "gdkconfig.h"
+
+#include <CoreGraphics/CoreGraphics.h>
+#include <cairo-quartz.h>
+
+#import "GdkMacosCairoView.h"
+
+#include "gdkmacoscairocontext-private.h"
+#include "gdkmacossurface-private.h"
+
+struct _GdkMacosCairoContext
+{
+  GdkCairoContext  parent_instance;
+
+  cairo_surface_t *window_surface;
+};
+
+struct _GdkMacosCairoContextClass
+{
+  GdkCairoContextClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkMacosCairoContext, _gdk_macos_cairo_context, GDK_TYPE_CAIRO_CONTEXT)
+
+static cairo_surface_t *
+create_cairo_surface_for_surface (GdkSurface *surface)
+{
+  cairo_surface_t *cairo_surface;
+  int scale;
+  int width;
+  int height;
+
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+
+  scale = gdk_surface_get_scale_factor (surface);
+  width = scale * gdk_surface_get_width (surface);
+  height = scale * gdk_surface_get_height (surface);
+
+  cairo_surface = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+
+  if (cairo_surface != NULL)
+    cairo_surface_set_device_scale (cairo_surface, scale, scale);
+
+  return cairo_surface;
+}
+
+static cairo_t *
+_gdk_macos_cairo_context_cairo_create (GdkCairoContext *cairo_context)
+{
+  GdkMacosCairoContext *self = (GdkMacosCairoContext *)cairo_context;
+
+  g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
+
+  return cairo_create (self->window_surface);
+}
+
+static void
+_gdk_macos_cairo_context_begin_frame (GdkDrawContext *draw_context,
+                                      cairo_region_t *region)
+{
+  GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
+  GdkSurface *surface;
+  NSWindow *nswindow;
+
+  g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
+
+  surface = gdk_draw_context_get_surface (draw_context);
+  nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface));
+
+  if (self->window_surface == NULL)
+    {
+      self->window_surface = create_cairo_surface_for_surface (surface);
+    }
+  else
+    {
+      if (![nswindow isOpaque])
+        {
+          cairo_t *cr = cairo_create (self->window_surface);
+          gdk_cairo_region (cr, region);
+          cairo_set_source_rgba (cr, 0, 0, 0, 0);
+          cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+          cairo_fill (cr);
+          cairo_destroy (cr);
+        }
+    }
+}
+
+static void
+_gdk_macos_cairo_context_end_frame (GdkDrawContext *draw_context,
+                                    cairo_region_t *painted)
+{
+  GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
+  GdkSurface *surface;
+  NSView *nsview;
+
+  g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
+  g_assert (self->window_surface != NULL);
+
+  surface = gdk_draw_context_get_surface (draw_context);
+  nsview = _gdk_macos_surface_get_view (GDK_MACOS_SURFACE (surface));
+
+  if (GDK_IS_MACOS_CAIRO_VIEW (nsview))
+    [(GdkMacosCairoView *)nsview setCairoSurface:self->window_surface
+                                      withDamage:painted];
+}
+
+static void
+_gdk_macos_cairo_context_surface_resized (GdkDrawContext *draw_context)
+{
+  GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
+
+  g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
+
+  g_clear_pointer (&self->window_surface, cairo_surface_destroy);
+}
+
+static void
+_gdk_macos_cairo_context_class_init (GdkMacosCairoContextClass *klass)
+{
+  GdkCairoContextClass *cairo_context_class = GDK_CAIRO_CONTEXT_CLASS (klass);
+  GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
+
+  draw_context_class->begin_frame = _gdk_macos_cairo_context_begin_frame;
+  draw_context_class->end_frame = _gdk_macos_cairo_context_end_frame;
+  draw_context_class->surface_resized = _gdk_macos_cairo_context_surface_resized;
+
+  cairo_context_class->cairo_create = _gdk_macos_cairo_context_cairo_create;
+}
+
+static void
+_gdk_macos_cairo_context_init (GdkMacosCairoContext *self)
+{
+}
diff --git a/gdk/macos/gdkmacosclipboard-private.h b/gdk/macos/gdkmacosclipboard-private.h
new file mode 100644 (file)
index 0000000..ab37d70
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_CLIPBOARD_PRIVATE_H__
+#define __GDK_MACOS_CLIPBOARD_PRIVATE_H__
+
+#include <AppKit/AppKit.h>
+
+#include "gdkclipboardprivate.h"
+#include "gdkmacosdisplay-private.h"
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_MACOS_CLIPBOARD (_gdk_macos_clipboard_get_type())
+
+G_DECLARE_FINAL_TYPE (GdkMacosClipboard, _gdk_macos_clipboard, GDK, MACOS_CLIPBOARD, GdkClipboard)
+
+GdkClipboard     *_gdk_macos_clipboard_new                       (GdkMacosDisplay   *display);
+void              _gdk_macos_clipboard_check_externally_modified (GdkMacosClipboard *self);
+NSPasteboardType  _gdk_macos_clipboard_to_ns_type                (const char        *mime_type,
+                                                                  NSPasteboardType  *alternate);
+const char       *_gdk_macos_clipboard_from_ns_type              (NSPasteboardType   ns_type);
+
+@interface GdkMacosClipboardDataProvider : NSObject <NSPasteboardItemDataProvider>
+{
+  GCancellable  *cancellable;
+  GdkClipboard  *clipboard;
+  char         **mimeTypes;
+}
+
+-(id)initClipboard:(GdkClipboard *)gdkClipboard mimetypes:(const char * const *)mime_types;
+-(NSArray<NSPasteboardType> *)types;
+
+@end
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_CLIPBOARD_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacosclipboard.c b/gdk/macos/gdkmacosclipboard.c
new file mode 100644 (file)
index 0000000..7297045
--- /dev/null
@@ -0,0 +1,576 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include "gdkmacosclipboard-private.h"
+#include "gdkmacosutils-private.h"
+
+struct _GdkMacosClipboard
+{
+  GdkClipboard  parent_instance;
+  NSPasteboard *pasteboard;
+  NSInteger     last_change_count;
+};
+
+typedef struct
+{
+  GMemoryOutputStream *stream;
+  NSPasteboardItem    *item;
+  NSPasteboardType     type;
+  GMainContext        *main_context;
+  guint                done : 1;
+} WriteRequest;
+
+G_DEFINE_TYPE (GdkMacosClipboard, _gdk_macos_clipboard, GDK_TYPE_CLIPBOARD)
+
+static void
+write_request_free (WriteRequest *wr)
+{
+  g_clear_pointer (&wr->main_context, g_main_context_unref);
+  g_clear_object (&wr->stream);
+  [wr->item release];
+  g_slice_free (WriteRequest, wr);
+}
+
+const char *
+_gdk_macos_clipboard_from_ns_type (NSPasteboardType type)
+{
+  G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+
+  if ([type isEqualToString:NSPasteboardTypeString] ||
+      [type isEqualToString:NSStringPboardType])
+    return g_intern_string ("text/plain;charset=utf-8");
+  else if ([type isEqualToString:NSPasteboardTypeURL] ||
+           [type isEqualToString:NSPasteboardTypeFileURL])
+    return g_intern_string ("text/uri-list");
+  else if ([type isEqualToString:NSPasteboardTypeColor])
+    return g_intern_string ("application/x-color");
+  else if ([type isEqualToString:NSPasteboardTypeTIFF])
+    return g_intern_string ("image/tiff");
+  else if ([type isEqualToString:NSPasteboardTypePNG])
+    return g_intern_string ("image/png");
+
+  G_GNUC_END_IGNORE_DEPRECATIONS;
+
+  return NULL;
+}
+
+NSPasteboardType
+_gdk_macos_clipboard_to_ns_type (const char       *mime_type,
+                                 NSPasteboardType *alternate)
+{
+  if (alternate)
+    *alternate = NULL;
+
+  if (g_strcmp0 (mime_type, "text/plain;charset=utf-8") == 0)
+    {
+      return NSPasteboardTypeString;
+    }
+  else if (g_strcmp0 (mime_type, "text/uri-list") == 0)
+    {
+      if (alternate)
+        *alternate = NSPasteboardTypeURL;
+      return NSPasteboardTypeFileURL;
+    }
+  else if (g_strcmp0 (mime_type, "application/x-color") == 0)
+    {
+      return NSPasteboardTypeColor;
+    }
+  else if (g_strcmp0 (mime_type, "image/tiff") == 0)
+    {
+      return NSPasteboardTypeTIFF;
+    }
+  else if (g_strcmp0 (mime_type, "image/png") == 0)
+    {
+      return NSPasteboardTypePNG;
+    }
+
+  return nil;
+}
+
+static void
+populate_content_formats (GdkContentFormatsBuilder *builder,
+                          NSPasteboardType          type)
+{
+  const char *mime_type;
+
+  g_return_if_fail (builder != NULL);
+  g_return_if_fail (type != NULL);
+
+  mime_type = _gdk_macos_clipboard_from_ns_type (type);
+
+  if (mime_type != NULL)
+    gdk_content_formats_builder_add_mime_type (builder, mime_type);
+}
+
+static GdkContentFormats *
+load_offer_formats (GdkMacosClipboard *self)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  GdkContentFormatsBuilder *builder;
+  GdkContentFormats *formats;
+
+  g_assert (GDK_IS_MACOS_CLIPBOARD (self));
+
+  builder = gdk_content_formats_builder_new ();
+  for (NSPasteboardType type in [self->pasteboard types])
+    populate_content_formats (builder, type);
+  formats = gdk_content_formats_builder_free_to_formats (builder);
+
+  GDK_END_MACOS_ALLOC_POOL;
+
+  return g_steal_pointer (&formats);
+}
+
+static void
+_gdk_macos_clipboard_load_contents (GdkMacosClipboard *self)
+{
+  GdkContentFormats *formats;
+  NSInteger change_count;
+
+  g_assert (GDK_IS_MACOS_CLIPBOARD (self));
+
+  change_count = [self->pasteboard changeCount];
+
+  formats = load_offer_formats (self);
+  gdk_clipboard_claim_remote (GDK_CLIPBOARD (self), formats);
+  gdk_content_formats_unref (formats);
+
+  self->last_change_count = change_count;
+}
+
+static GInputStream *
+create_stream_from_nsdata (NSData *data)
+{
+  const guint8 *bytes = [data bytes];
+  gsize len = [data length];
+
+  return g_memory_input_stream_new_from_data (g_memdup (bytes, len), len, g_free);
+}
+
+static void
+_gdk_macos_clipboard_read_async (GdkClipboard        *clipboard,
+                                 GdkContentFormats   *formats,
+                                 int                  io_priority,
+                                 GCancellable        *cancellable,
+                                 GAsyncReadyCallback  callback,
+                                 gpointer             user_data)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  GdkMacosClipboard *self = (GdkMacosClipboard *)clipboard;
+  GdkContentFormats *offer_formats = NULL;
+  const char *mime_type;
+  GInputStream *stream = NULL;
+  GTask *task = NULL;
+
+  g_assert (GDK_IS_MACOS_CLIPBOARD (self));
+  g_assert (formats != NULL);
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_source_tag (task, _gdk_macos_clipboard_read_async);
+  g_task_set_priority (task, io_priority);
+
+  offer_formats = load_offer_formats (GDK_MACOS_CLIPBOARD (clipboard));
+  mime_type = gdk_content_formats_match_mime_type (formats, offer_formats);
+
+  if (mime_type == NULL)
+    {
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_NOT_SUPPORTED,
+                               "%s",
+                               _("No compatible transfer format found"));
+      goto cleanup;
+    }
+
+  if (strcmp (mime_type, "text/plain;charset=utf-8") == 0)
+    {
+      NSString *nsstr = [self->pasteboard stringForType:NSPasteboardTypeString];
+
+      if (nsstr != NULL)
+        {
+          const char *str = [nsstr UTF8String];
+          stream = g_memory_input_stream_new_from_data (g_strdup (str),
+                                                        strlen (str) + 1,
+                                                        g_free);
+        }
+    }
+  else if (strcmp (mime_type, "text/uri-list") == 0)
+    {
+      G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+
+      if ([[self->pasteboard types] containsObject:NSPasteboardTypeFileURL])
+        {
+          GString *str = g_string_new (NULL);
+          NSArray *files = [self->pasteboard propertyListForType:NSFilenamesPboardType];
+          gsize n_files = [files count];
+          char *data;
+          guint len;
+
+          for (gsize i = 0; i < n_files; ++i)
+            {
+              NSString* uriString = [files objectAtIndex:i];
+              uriString = [@"file://" stringByAppendingString:uriString];
+              uriString = [uriString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
+
+              g_string_append_printf (str,
+                                      "%s\r\n",
+                                      [uriString cStringUsingEncoding:NSUTF8StringEncoding]);
+            }
+
+          len = str->len;
+          data = g_string_free (str, FALSE);
+          stream = g_memory_input_stream_new_from_data (data, len, g_free);
+        }
+
+      G_GNUC_END_IGNORE_DEPRECATIONS;
+    }
+  else if (strcmp (mime_type, "application/x-color") == 0)
+    {
+      NSColorSpace *colorspace;
+      NSColor *nscolor;
+      guint16 color[4];
+
+      colorspace = [NSColorSpace genericRGBColorSpace];
+      nscolor = [[NSColor colorFromPasteboard:self->pasteboard]
+                    colorUsingColorSpace:colorspace];
+
+      color[0] = 0xffff * [nscolor redComponent];
+      color[1] = 0xffff * [nscolor greenComponent];
+      color[2] = 0xffff * [nscolor blueComponent];
+      color[3] = 0xffff * [nscolor alphaComponent];
+
+      stream = g_memory_input_stream_new_from_data (g_memdup (&color, sizeof color),
+                                                    sizeof color,
+                                                    g_free);
+    }
+  else if (strcmp (mime_type, "image/tiff") == 0)
+    {
+      NSData *data = [self->pasteboard dataForType:NSPasteboardTypeTIFF];
+      stream = create_stream_from_nsdata (data);
+    }
+  else if (strcmp (mime_type, "image/png") == 0)
+    {
+      NSData *data = [self->pasteboard dataForType:NSPasteboardTypePNG];
+      stream = create_stream_from_nsdata (data);
+    }
+
+  if (stream != NULL)
+    {
+      g_task_set_task_data (task, g_strdup (mime_type), g_free);
+      g_task_return_pointer (task, g_steal_pointer (&stream), g_object_unref);
+    }
+  else
+    {
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_FAILED,
+                               _("Failed to decode contents with mime-type of '%s'"),
+                               mime_type);
+    }
+
+cleanup:
+  g_clear_object (&task);
+  g_clear_pointer (&offer_formats, gdk_content_formats_unref);
+
+  GDK_END_MACOS_ALLOC_POOL;
+}
+
+static GInputStream *
+_gdk_macos_clipboard_read_finish (GdkClipboard  *clipboard,
+                                  GAsyncResult  *result,
+                                  const char   **out_mime_type,
+                                  GError       **error)
+{
+  GTask *task = (GTask *)result;
+
+  g_assert (GDK_IS_MACOS_CLIPBOARD (clipboard));
+  g_assert (G_IS_TASK (task));
+
+  if (out_mime_type != NULL)
+    *out_mime_type = g_strdup (g_task_get_task_data (task));
+
+  return g_task_propagate_pointer (task, error);
+}
+
+static void
+_gdk_macos_clipboard_send_to_pasteboard (GdkMacosClipboard  *self,
+                                         GdkContentProvider *content)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  GdkMacosClipboardDataProvider *dataProvider;
+  GdkContentFormats *serializable;
+  NSPasteboardItem *item;
+  const char * const *mime_types;
+  gsize n_mime_types;
+
+  g_return_if_fail (GDK_IS_MACOS_CLIPBOARD (self));
+  g_return_if_fail (GDK_IS_CONTENT_PROVIDER (content));
+
+  serializable = gdk_content_provider_ref_storable_formats (content);
+  serializable = gdk_content_formats_union_serialize_mime_types (serializable);
+  mime_types = gdk_content_formats_get_mime_types (serializable, &n_mime_types);
+
+  dataProvider = [[GdkMacosClipboardDataProvider alloc] initClipboard:GDK_CLIPBOARD (self)
+                                                            mimetypes:mime_types];
+  item = [[NSPasteboardItem alloc] init];
+  [item setDataProvider:dataProvider forTypes:[dataProvider types]];
+
+  [self->pasteboard clearContents];
+  if ([self->pasteboard writeObjects:[NSArray arrayWithObject:item]] == NO)
+    g_warning ("Failed to write object to pasteboard");
+
+  self->last_change_count = [self->pasteboard changeCount];
+
+  g_clear_pointer (&serializable, gdk_content_formats_unref);
+
+  GDK_END_MACOS_ALLOC_POOL;
+}
+
+static gboolean
+_gdk_macos_clipboard_claim (GdkClipboard       *clipboard,
+                            GdkContentFormats  *formats,
+                            gboolean            local,
+                            GdkContentProvider *provider)
+{
+  GdkMacosClipboard *self = (GdkMacosClipboard *)clipboard;
+  gboolean ret;
+
+  g_assert (GDK_IS_CLIPBOARD (clipboard));
+  g_assert (formats != NULL);
+  g_assert (!provider || GDK_IS_CONTENT_PROVIDER (provider));
+
+  ret = GDK_CLIPBOARD_CLASS (_gdk_macos_clipboard_parent_class)->claim (clipboard, formats, local, provider);
+
+  if (local)
+    _gdk_macos_clipboard_send_to_pasteboard (self, provider);
+
+  return ret;
+}
+
+static void
+_gdk_macos_clipboard_constructed (GObject *object)
+{
+  GdkMacosClipboard *self = (GdkMacosClipboard *)object;
+
+  if (self->pasteboard == nil)
+    self->pasteboard = [[NSPasteboard generalPasteboard] retain];
+
+  G_OBJECT_CLASS (_gdk_macos_clipboard_parent_class)->constructed (object);
+}
+
+static void
+_gdk_macos_clipboard_finalize (GObject *object)
+{
+  GdkMacosClipboard *self = (GdkMacosClipboard *)object;
+
+  if (self->pasteboard != nil)
+    {
+      [self->pasteboard release];
+      self->pasteboard = nil;
+    }
+
+  G_OBJECT_CLASS (_gdk_macos_clipboard_parent_class)->finalize (object);
+}
+
+static void
+_gdk_macos_clipboard_class_init (GdkMacosClipboardClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkClipboardClass *clipboard_class = GDK_CLIPBOARD_CLASS (klass);
+
+  object_class->constructed = _gdk_macos_clipboard_constructed;
+  object_class->finalize = _gdk_macos_clipboard_finalize;
+
+  clipboard_class->claim = _gdk_macos_clipboard_claim;
+  clipboard_class->read_async = _gdk_macos_clipboard_read_async;
+  clipboard_class->read_finish = _gdk_macos_clipboard_read_finish;
+}
+
+static void
+_gdk_macos_clipboard_init (GdkMacosClipboard *self)
+{
+}
+
+GdkClipboard *
+_gdk_macos_clipboard_new (GdkMacosDisplay *display)
+{
+  GdkMacosClipboard *self;
+
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
+
+  self = g_object_new (GDK_TYPE_MACOS_CLIPBOARD,
+                       "display", display,
+                       NULL);
+
+  _gdk_macos_clipboard_load_contents (self);
+
+  return GDK_CLIPBOARD (self);
+}
+
+void
+_gdk_macos_clipboard_check_externally_modified (GdkMacosClipboard *self)
+{
+  g_return_if_fail (GDK_IS_MACOS_CLIPBOARD (self));
+
+  if ([self->pasteboard changeCount] != self->last_change_count)
+    _gdk_macos_clipboard_load_contents (self);
+}
+
+@implementation GdkMacosClipboardDataProvider
+
+-(id)initClipboard:(GdkClipboard *)gdkClipboard mimetypes:(const char * const *)mime_types;
+{
+  [super init];
+
+  self->mimeTypes = g_strdupv ((char **)mime_types);
+  self->clipboard = g_object_ref (gdkClipboard);
+
+  return self;
+}
+
+-(void)dealloc
+{
+  g_cancellable_cancel (self->cancellable);
+
+  g_clear_pointer (&self->mimeTypes, g_strfreev);
+  g_clear_object (&self->clipboard);
+  g_clear_object (&self->cancellable);
+
+  [super dealloc];
+}
+
+-(void)pasteboardFinishedWithDataProvider:(NSPasteboard *)pasteboard
+{
+  g_clear_object (&self->clipboard);
+}
+
+-(NSArray<NSPasteboardType> *)types
+{
+  NSMutableArray *ret = [[NSMutableArray alloc] init];
+
+  for (guint i = 0; self->mimeTypes[i]; i++)
+    {
+      const char *mime_type = self->mimeTypes[i];
+      NSPasteboardType type;
+      NSPasteboardType alternate = nil;
+
+      if ((type = _gdk_macos_clipboard_to_ns_type (mime_type, &alternate)))
+        {
+          [ret addObject:type];
+          if (alternate)
+            [ret addObject:alternate];
+        }
+    }
+
+  return g_steal_pointer (&ret);
+}
+
+static void
+on_data_ready_cb (GObject      *object,
+                  GAsyncResult *result,
+                  gpointer      user_data)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  GdkClipboard *clipboard = (GdkClipboard *)object;
+  WriteRequest *wr = user_data;
+  GError *error = NULL;
+  NSData *data = nil;
+
+  g_assert (GDK_IS_CLIPBOARD (clipboard));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (wr != NULL);
+  g_assert (G_IS_MEMORY_OUTPUT_STREAM (wr->stream));
+  g_assert ([wr->item isKindOfClass:[NSPasteboardItem class]]);
+
+  if (gdk_clipboard_write_finish (clipboard, result, &error))
+    {
+      gsize size;
+      gpointer bytes;
+
+      g_output_stream_close (G_OUTPUT_STREAM (wr->stream), NULL, NULL);
+
+      size = g_memory_output_stream_get_size (wr->stream);
+      bytes = g_memory_output_stream_steal_data (wr->stream);
+      data = [[NSData alloc] initWithBytesNoCopy:bytes
+                                          length:size
+                                     deallocator:^(void *alloc, NSUInteger length) { g_free (alloc); }];
+    }
+  else
+    {
+      g_warning ("Failed to serialize clipboard contents: %s",
+                 error->message);
+      g_clear_error (&error);
+    }
+
+  [wr->item setData:data forType:wr->type];
+
+  wr->done = TRUE;
+
+  GDK_END_MACOS_ALLOC_POOL;
+}
+
+-(void)   pasteboard:(NSPasteboard *)pasteboard
+                item:(NSPasteboardItem *)item
+  provideDataForType:(NSPasteboardType)type
+{
+  const char *mime_type = _gdk_macos_clipboard_from_ns_type (type);
+  GMainContext *main_context = g_main_context_default ();
+  WriteRequest *wr;
+
+  if (self->clipboard == NULL || mime_type == NULL)
+    {
+      [item setData:[NSData data] forType:type];
+      return;
+    }
+
+  wr = g_slice_new0 (WriteRequest);
+  wr->item = [item retain];
+  wr->stream = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new_resizable ());
+  wr->type = type;
+  wr->main_context = g_main_context_ref (main_context);
+  wr->done = FALSE;
+
+  gdk_clipboard_write_async (self->clipboard,
+                             mime_type,
+                             G_OUTPUT_STREAM (wr->stream),
+                             G_PRIORITY_DEFAULT,
+                             self->cancellable,
+                             on_data_ready_cb,
+                             wr);
+
+  /* We're forced to provide data synchronously via this API
+   * so we must block on the main loop. Using another main loop
+   * than the default tends to get us locked up here, so that is
+   * what we'll do for now.
+   */
+  while (!wr->done)
+    g_main_context_iteration (wr->main_context, TRUE);
+
+  write_request_free (wr);
+}
+
+@end
diff --git a/gdk/macos/gdkmacoscursor-private.h b/gdk/macos/gdkmacoscursor-private.h
new file mode 100644 (file)
index 0000000..b3e5bac
--- /dev/null
@@ -0,0 +1,32 @@
+/* gdkmacoscursor-private.h
+ *
+ * Copyright (C) 2005-2007 Imendio AB
+ * Copyright (C) 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GDK_MACOS_CURSOR_PRIVATE_H__
+#define __GDK_MACOS_CURSOR_PRIVATE_H__
+
+#include <AppKit/AppKit.h>
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+NSCursor *_gdk_macos_cursor_get_ns_cursor (GdkCursor *cursor);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_CURSOR_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacoscursor.c b/gdk/macos/gdkmacoscursor.c
new file mode 100644 (file)
index 0000000..a6da5c9
--- /dev/null
@@ -0,0 +1,181 @@
+/* gdkcursor-macos.c
+ *
+ * Copyright (C) 2005-2007 Imendio AB
+ * Copyright (C) 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "gdkmacoscursor-private.h"
+
+/* OS X only exports a number of cursor types in its public NSCursor interface.
+ * By overriding the private _coreCursorType method, we can tell OS X to load
+ * one of its internal cursors instead (since cursor images are loaded on demand
+ * instead of in advance). WebKit does this too.
+ */
+
+@interface gdkCoreCursor : NSCursor {
+@private
+        int type;
+        BOOL override;
+}
+@end
+
+@implementation gdkCoreCursor
+
+- (long long)_coreCursorType
+{
+  if (self->override)
+    return self->type;
+  return [super _coreCursorType];
+}
+
+#define CUSTOM_CURSOR_CTOR(name, id) \
+        + (gdkCoreCursor *)name \
+        { \
+                gdkCoreCursor *obj; \
+                obj = [self new]; \
+                if (obj) { \
+                        obj->override = YES; \
+                        obj->type = id; \
+                } \
+                return obj; \
+        }
+CUSTOM_CURSOR_CTOR(gdkHelpCursor, 40)
+CUSTOM_CURSOR_CTOR(gdkProgressCursor, 4)
+/* TODO OS X doesn't seem to have a way to get this. There is an undocumented
+ * method +[NSCursor _waitCursor], but it doesn't actually return this cursor,
+ * but rather some odd low-quality non-animating version of this cursor. Use
+ * the progress cursor instead for now.
+ */
+CUSTOM_CURSOR_CTOR(gdkWaitCursor, 4)
+CUSTOM_CURSOR_CTOR(gdkAliasCursor, 2)
+CUSTOM_CURSOR_CTOR(gdkMoveCursor, 39)
+/* TODO OS X doesn't seem to provide one; copy the move cursor for now
+ *  since it looks similar to what we want. */
+CUSTOM_CURSOR_CTOR(gdkAllScrollCursor, 39)
+CUSTOM_CURSOR_CTOR(gdkNEResizeCursor, 29)
+CUSTOM_CURSOR_CTOR(gdkNWResizeCursor, 33)
+CUSTOM_CURSOR_CTOR(gdkSEResizeCursor, 35)
+CUSTOM_CURSOR_CTOR(gdkSWResizeCursor, 37)
+CUSTOM_CURSOR_CTOR(gdkEWResizeCursor, 28)
+CUSTOM_CURSOR_CTOR(gdkNSResizeCursor, 32)
+CUSTOM_CURSOR_CTOR(gdkNESWResizeCursor, 30)
+CUSTOM_CURSOR_CTOR(gdkNWSEResizeCursor, 34)
+CUSTOM_CURSOR_CTOR(gdkZoomInCursor, 42)
+CUSTOM_CURSOR_CTOR(gdkZoomOutCursor, 43)
+#undef CUSTOM_CURSOR_CTOR
+
+@end
+
+struct CursorsByName {
+  const gchar *name;
+  NSString *selector;
+};
+
+static const struct CursorsByName cursors_by_name[] = {
+  /* Link & Status */
+  { "context-menu", @"contextualMenuCursor" },
+  { "help", @"gdkHelpCursor" },
+  { "pointer", @"pointingHandCursor" },
+  { "progress", @"gdkProgressCursor" },
+  { "wait", @"gdkWaitCursor" },
+  /* Selection */
+  { "cell", @"crosshairCursor" },
+  { "crosshair", @"crosshairCursor" },
+  { "text", @"IBeamCursor" },
+  { "vertical-text", @"IBeamCursorForVerticalLayout" },
+  /* Drag & Drop */
+  { "alias", @"gdkAliasCursor" },
+  { "copy", @"dragCopyCursor" },
+  { "move", @"gdkMoveCursor" },
+  { "no-drop", @"operationNotAllowedCursor" },
+  { "not-allowed", @"operationNotAllowedCursor" },
+  { "grab", @"openHandCursor" },
+  { "grabbing", @"closedHandCursor" },
+  /* Resize & Scrolling */
+  { "all-scroll", @"gdkAllScrollCursor" },
+  { "col-resize", @"resizeLeftRightCursor" },
+  { "row-resize", @"resizeUpDownCursor" },
+
+  /* Undocumented cursors to match native resizing */
+  { "e-resize", @"_windowResizeEastWestCursor" },
+  { "w-resize", @"_windowResizeEastWestCursor" },
+  { "n-resize", @"_windowResizeNorthSouthCursor" },
+  { "s-resize", @"_windowResizeNorthSouthCursor" },
+
+  { "ne-resize", @"gdkNEResizeCursor" },
+  { "nw-resize", @"gdkNWResizeCursor" },
+  { "se-resize", @"gdkSEResizeCursor" },
+  { "sw-resize", @"gdkSWResizeCursor" },
+  { "ew-resize", @"gdkEWResizeCursor" },
+  { "ns-resize", @"gdkNSResizeCursor" },
+  { "nesw-resize", @"gdkNESWResizeCursor" },
+  { "nwse-resize", @"gdkNWSEResizeCursor" },
+  /* Zoom */
+  { "zoom-in", @"gdkZoomInCursor" },
+  { "zoom-out", @"gdkZoomOutCursor" },
+};
+
+static NSCursor *
+create_blank_cursor (void)
+{
+  NSCursor *nscursor;
+  NSImage *nsimage;
+  NSSize size = { 1.0, 1.0 };
+
+  nsimage = [[NSImage alloc] initWithSize:size];
+  nscursor = [[NSCursor alloc] initWithImage:nsimage
+                               hotSpot:NSMakePoint(0.0, 0.0)];
+  [nsimage release];
+
+  return nscursor;
+}
+
+NSCursor *
+_gdk_macos_cursor_get_ns_cursor (GdkCursor *cursor)
+{
+  const char *name = NULL;
+  NSCursor *nscursor;
+  SEL selector = @selector(arrowCursor);
+
+  g_return_val_if_fail (!cursor || GDK_IS_CURSOR (cursor), NULL);
+
+  if (cursor != NULL)
+    name = gdk_cursor_get_name (cursor);
+
+  if (name == NULL)
+    goto load_cursor;
+
+  if (strcmp (name, "none") == 0)
+    return create_blank_cursor ();
+
+  for (guint i = 0; i < G_N_ELEMENTS (cursors_by_name); i++)
+    {
+      if (strcmp (cursors_by_name[i].name, name) == 0)
+        {
+          selector = NSSelectorFromString (cursors_by_name[i].selector);
+          break;
+        }
+    }
+
+load_cursor:
+  nscursor = [[gdkCoreCursor class] performSelector:selector];
+  [nscursor retain];
+  return nscursor;
+}
diff --git a/gdk/macos/gdkmacosdevice.c b/gdk/macos/gdkmacosdevice.c
new file mode 100644 (file)
index 0000000..8e621fa
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2009 Carlos Garnacho <carlosg@gnome.org>
+ * Copyright 2010 Kristian Rietveld <kris@gtk.org>
+ * Copyright 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include <gdk/gdk.h>
+
+#include "gdkdeviceprivate.h"
+#include "gdkdisplayprivate.h"
+
+#include "gdkmacoscursor-private.h"
+#include "gdkmacosdevice.h"
+#include "gdkmacosdisplay-private.h"
+#include "gdkmacossurface-private.h"
+
+struct _GdkMacosDevice
+{
+  GdkDevice parent_instance;
+};
+
+struct _GdkMacosDeviceClass
+{
+  GdkDeviceClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkMacosDevice, gdk_macos_device, GDK_TYPE_DEVICE)
+
+static void
+gdk_macos_device_set_surface_cursor (GdkDevice  *device,
+                                     GdkSurface *surface,
+                                     GdkCursor  *cursor)
+{
+  NSCursor *nscursor;
+
+  g_assert (GDK_IS_MACOS_DEVICE (device));
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+  g_assert (!cursor || GDK_IS_CURSOR (cursor));
+
+  nscursor = _gdk_macos_cursor_get_ns_cursor (cursor);
+
+  if (nscursor != NULL)
+    {
+      [nscursor set];
+      [nscursor release];
+    }
+}
+
+static GdkSurface *
+gdk_macos_device_surface_at_position (GdkDevice       *device,
+                                      gdouble         *win_x,
+                                      gdouble         *win_y,
+                                      GdkModifierType *state)
+{
+  GdkMacosDisplay *display;
+  GdkMacosSurface *surface;
+  NSPoint point;
+  gint x;
+  gint y;
+
+  g_assert (GDK_IS_MACOS_DEVICE (device));
+  g_assert (win_x != NULL);
+  g_assert (win_y != NULL);
+
+  point = [NSEvent mouseLocation];
+  display = GDK_MACOS_DISPLAY (gdk_device_get_display (device));
+
+  if (state != NULL)
+    *state = (_gdk_macos_display_get_current_keyboard_modifiers (display) |
+              _gdk_macos_display_get_current_mouse_modifiers (display));
+
+  surface = _gdk_macos_display_get_surface_at_display_coords (display, point.x, point.y, &x, &y);
+
+  *win_x = x;
+  *win_y = y;
+
+  return GDK_SURFACE (surface);
+}
+
+static GdkGrabStatus
+gdk_macos_device_grab (GdkDevice    *device,
+                       GdkSurface   *window,
+                       gboolean      owner_events,
+                       GdkEventMask  event_mask,
+                       GdkSurface   *confine_to,
+                       GdkCursor    *cursor,
+                       guint32       time_)
+{
+  /* Should remain empty */
+  return GDK_GRAB_SUCCESS;
+}
+
+static void
+gdk_macos_device_ungrab (GdkDevice *device,
+                         guint32    time_)
+{
+  GdkMacosDevice *self = (GdkMacosDevice *)device;
+  GdkDeviceGrabInfo *grab;
+  GdkDisplay *display;
+
+  g_assert (GDK_IS_MACOS_DEVICE (self));
+
+  display = gdk_device_get_display (device);
+  grab = _gdk_display_get_last_device_grab (display, device);
+
+  if (grab != NULL)
+    grab->serial_end = 0;
+
+  _gdk_display_device_grab_update (display, device, device, 0);
+}
+
+static void
+gdk_macos_device_get_state (GdkDevice       *device,
+                            GdkSurface      *surface,
+                            gdouble         *axes,
+                            GdkModifierType *mask)
+{
+  gdouble x_pos, y_pos;
+
+  g_assert (GDK_IS_MACOS_DEVICE (device));
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+
+  gdk_surface_get_device_position (surface, device, &x_pos, &y_pos, mask);
+
+  if (axes != NULL)
+    {
+      axes[0] = x_pos;
+      axes[1] = y_pos;
+    }
+}
+
+static void
+gdk_macos_device_query_state (GdkDevice        *device,
+                              GdkSurface       *surface,
+                              GdkSurface      **child_surface,
+                              gdouble          *win_x,
+                              gdouble          *win_y,
+                              GdkModifierType  *mask)
+{
+  GdkDisplay *display;
+  NSPoint point;
+  int sx = 0;
+  int sy = 0;
+  int x_tmp;
+  int y_tmp;
+
+  g_assert (GDK_IS_MACOS_DEVICE (device));
+  g_assert (!surface || GDK_IS_MACOS_SURFACE (surface));
+
+  if (child_surface)
+    *child_surface = surface;
+
+  display = gdk_device_get_display (device);
+  point = [NSEvent mouseLocation];
+  _gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (display),
+                                          point.x, point.y,
+                                          &x_tmp, &y_tmp);
+
+  if (surface)
+    _gdk_macos_surface_get_root_coords (GDK_MACOS_SURFACE (surface), &sx, &sy);
+
+  if (win_x)
+    *win_x = x_tmp - sx;
+
+  if (win_y)
+    *win_y = y_tmp - sy;
+
+  if (mask)
+    *mask = _gdk_macos_display_get_current_keyboard_modifiers (GDK_MACOS_DISPLAY (display)) |
+            _gdk_macos_display_get_current_mouse_modifiers (GDK_MACOS_DISPLAY (display));
+}
+
+static void
+gdk_macos_device_class_init (GdkMacosDeviceClass *klass)
+{
+  GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
+
+  device_class->get_state = gdk_macos_device_get_state;
+  device_class->grab = gdk_macos_device_grab;
+  device_class->query_state = gdk_macos_device_query_state;
+  device_class->set_surface_cursor = gdk_macos_device_set_surface_cursor;
+  device_class->surface_at_position = gdk_macos_device_surface_at_position;
+  device_class->ungrab = gdk_macos_device_ungrab;
+}
+
+static void
+gdk_macos_device_init (GdkMacosDevice *self)
+{
+  _gdk_device_add_axis (GDK_DEVICE (self), GDK_AXIS_X, 0, 0, 1);
+  _gdk_device_add_axis (GDK_DEVICE (self), GDK_AXIS_Y, 0, 0, 1);
+}
diff --git a/gdk/macos/gdkmacosdevice.h b/gdk/macos/gdkmacosdevice.h
new file mode 100644 (file)
index 0000000..c81fde5
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_DEVICE_H__
+#define __GDK_MACOS_DEVICE_H__
+
+#if !defined (__GDKMACOS_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gdk/macos/gdkmacos.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GdkMacosDevice      GdkMacosDevice;
+typedef struct _GdkMacosDeviceClass GdkMacosDeviceClass;
+
+#define GDK_TYPE_MACOS_DEVICE       (gdk_macos_device_get_type())
+#define GDK_MACOS_DEVICE(object)    (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_DEVICE, GdkMacosDevice))
+#define GDK_IS_MACOS_DEVICE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_DEVICE))
+
+GDK_AVAILABLE_IN_ALL
+GType gdk_macos_device_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_DEVICE_H__ */
diff --git a/gdk/macos/gdkmacosdisplay-private.h b/gdk/macos/gdkmacosdisplay-private.h
new file mode 100644 (file)
index 0000000..9f3d558
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_DISPLAY_PRIVATE_H__
+#define __GDK_MACOS_DISPLAY_PRIVATE_H__
+
+#include <AppKit/AppKit.h>
+
+#include "gdkdisplayprivate.h"
+
+#include "gdkmacosdisplay.h"
+#include "gdkmacoskeymap.h"
+#include "gdkmacossurface.h"
+
+G_BEGIN_DECLS
+
+struct _GdkMacosDisplay
+{
+  GdkDisplay parent_instance;
+
+  char *name;
+  GdkMacosKeymap *keymap;
+
+  /* An list of GdkMacosMonitor. The first instance is always the primary
+   * monitor. This contains the 0,0 coordinate in quartz coordinates, but may
+   * not be 0,0 in GDK coordinates.
+   */
+  GListStore *monitors;
+
+  /* A queue of surfaces that have been made "main" so that we can update the
+   * main status to the next surface when a window has lost main status (such
+   * as when destroyed). This uses the GdkMacosSurface main link.
+   */
+  GQueue main_surfaces;
+
+  /* A queue of surfaces sorted by their front-to-back ordering on the screen.
+   * This is updated occasionally when we know that the data we have cached
+   * has been invalidated. This uses the GdkMacosSurface.sorted link.
+   */
+  GQueue sorted_surfaces;
+
+  /* Our CVDisplayLink based GSource which we use to freeze/thaw the
+   * GdkFrameClock for the surface.
+   */
+  GSource *frame_source;
+
+  /* A queue of surfaces which we know are awaiting frames to be drawn. This
+   * uses the GdkMacosSurface.frame link.
+   */
+  GQueue awaiting_frames;
+
+  /* The surface that is receiving keyboard events */
+  GdkMacosSurface *keyboard_surface;
+
+  /* Used to translate from quartz coordinate space to GDK */
+  int width;
+  int height;
+  int min_x;
+  int min_y;
+  int max_x;
+  int max_y;
+};
+
+struct _GdkMacosDisplayClass
+{
+  GdkDisplayClass parent_class;
+};
+
+
+GdkDisplay      *_gdk_macos_display_open                           (const gchar     *display_name);
+int              _gdk_macos_display_get_fd                         (GdkMacosDisplay *self);
+void             _gdk_macos_display_queue_events                   (GdkMacosDisplay *self);
+void             _gdk_macos_display_to_display_coords              (GdkMacosDisplay *self,
+                                                                    int              x,
+                                                                    int              y,
+                                                                    int             *out_x,
+                                                                    int             *out_y);
+void             _gdk_macos_display_from_display_coords            (GdkMacosDisplay *self,
+                                                                    int              x,
+                                                                    int              y,
+                                                                    int             *out_x,
+                                                                    int             *out_y);
+NSScreen        *_gdk_macos_display_get_screen_at_display_coords   (GdkMacosDisplay *self,
+                                                                    int              x,
+                                                                    int              y);
+GdkMonitor      *_gdk_macos_display_get_monitor_at_coords          (GdkMacosDisplay *self,
+                                                                    int              x,
+                                                                    int              y);
+GdkMonitor      *_gdk_macos_display_get_monitor_at_display_coords  (GdkMacosDisplay *self,
+                                                                    int              x,
+                                                                    int              y);
+GdkEvent        *_gdk_macos_display_translate                      (GdkMacosDisplay *self,
+                                                                    NSEvent         *event);
+void             _gdk_macos_display_break_all_grabs                (GdkMacosDisplay *self,
+                                                                    guint32          time);
+GdkModifierType  _gdk_macos_display_get_current_keyboard_modifiers (GdkMacosDisplay *self);
+GdkModifierType  _gdk_macos_display_get_current_mouse_modifiers    (GdkMacosDisplay *self);
+GdkMacosSurface *_gdk_macos_display_get_surface_at_display_coords  (GdkMacosDisplay *self,
+                                                                    double           x,
+                                                                    double           y,
+                                                                    int             *surface_x,
+                                                                    int             *surface_y);
+void             _gdk_macos_display_reload_monitors                (GdkMacosDisplay *self);
+void             _gdk_macos_display_surface_removed                (GdkMacosDisplay *self,
+                                                                    GdkMacosSurface *surface);
+void             _gdk_macos_display_add_frame_callback             (GdkMacosDisplay *self,
+                                                                    GdkMacosSurface *surface);
+void             _gdk_macos_display_remove_frame_callback          (GdkMacosDisplay *self,
+                                                                    GdkMacosSurface *surface);
+void             _gdk_macos_display_synthesize_motion              (GdkMacosDisplay *self,
+                                                                    GdkMacosSurface *surface);
+NSWindow        *_gdk_macos_display_find_native_under_pointer      (GdkMacosDisplay *self,
+                                                                    int             *x,
+                                                                    int             *y);
+gboolean         _gdk_macos_display_get_setting                    (GdkMacosDisplay *self,
+                                                                    const gchar     *setting,
+                                                                    GValue          *value);
+void             _gdk_macos_display_reload_settings                (GdkMacosDisplay *self);
+void             _gdk_macos_display_surface_resigned_main          (GdkMacosDisplay *self,
+                                                                    GdkMacosSurface *surface);
+void             _gdk_macos_display_surface_became_main            (GdkMacosDisplay *self,
+                                                                    GdkMacosSurface *surface);
+void             _gdk_macos_display_surface_resigned_key           (GdkMacosDisplay *self,
+                                                                    GdkMacosSurface *surface);
+void             _gdk_macos_display_surface_became_key             (GdkMacosDisplay *self,
+                                                                    GdkMacosSurface *surface);
+int              _gdk_macos_display_get_nominal_refresh_rate       (GdkMacosDisplay *self);
+void             _gdk_macos_display_clear_sorting                  (GdkMacosDisplay *self);
+const GList     *_gdk_macos_display_get_surfaces                   (GdkMacosDisplay *self);
+void             _gdk_macos_display_send_button_event              (GdkMacosDisplay *self,
+                                                                    NSEvent         *nsevent);
+void             _gdk_macos_display_warp_pointer                   (GdkMacosDisplay *self,
+                                                                    int              x,
+                                                                    int              y);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_DISPLAY_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacosdisplay-settings.c b/gdk/macos/gdkmacosdisplay-settings.c
new file mode 100644 (file)
index 0000000..558e0b8
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright © 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * Copyright © 1998-2002 Tor Lillqvist
+ * Copyright © 2005-2008 Imendio AB
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include <AppKit/AppKit.h>
+
+#include "gdkdisplayprivate.h"
+
+#include "gdkmacosdisplay-private.h"
+#include "gdkmacosutils-private.h"
+
+typedef struct
+{
+  const char *font_name;
+  int         xft_dpi;
+  int         double_click_time;
+  int         cursor_blink_timeout;
+  guint       enable_animations : 1;
+  guint       shell_shows_desktop : 1;
+  guint       shell_shows_menubar : 1;
+  guint       primary_button_warps_slider : 1;
+} GdkMacosSettings;
+
+static GdkMacosSettings current_settings;
+static gboolean current_settings_initialized;
+
+static void
+_gdk_macos_settings_load (GdkMacosSettings *settings)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+  NSString *name;
+  NSInteger ival;
+  float fval;
+  char *str;
+  int pt_size;
+
+  g_assert (settings != NULL);
+
+  settings->shell_shows_desktop = TRUE;
+  settings->shell_shows_menubar = TRUE;
+  settings->enable_animations = TRUE;
+  settings->xft_dpi = 72 * 1024;
+
+  ival = [defaults integerForKey:@"NSTextInsertionPointBlinkPeriod"];
+  if (ival > 0)
+    settings->cursor_blink_timeout = ival;
+  else
+    settings->cursor_blink_timeout = 1000;
+
+  settings->primary_button_warps_slider =
+      [[NSUserDefaults standardUserDefaults] boolForKey:@"AppleScrollerPagingBehavior"] == YES;
+
+  fval = [defaults floatForKey:@"com.apple.mouse.doubleClickThreshold"];
+  if (fval == 0.0)
+    fval = 0.5;
+  settings->double_click_time = fval * 1000;
+
+  name = [[NSFont systemFontOfSize:0] familyName];
+  pt_size = (gint)[[NSFont userFontOfSize:0] pointSize];
+  /* Let's try to use the "views" font size (12pt) by default. This is
+   * used for lists/text/other "content" which is the largest parts of
+   * apps, using the "regular control" size (13pt) looks a bit out of
+   * place. We might have to tweak this.
+   *
+   * The size has to be hardcoded as there doesn't seem to be a way to
+   * get the views font size programmatically.
+   */
+  str = g_strdup_printf ("%s %d", [name UTF8String], pt_size);
+  settings->font_name = g_intern_string (str);
+  g_free (str);
+
+  GDK_END_MACOS_ALLOC_POOL;
+}
+
+gboolean
+_gdk_macos_display_get_setting (GdkMacosDisplay *self,
+                                const gchar     *setting,
+                                GValue          *value)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  gboolean ret = FALSE;
+
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), FALSE);
+  g_return_val_if_fail (setting != NULL, FALSE);
+  g_return_val_if_fail (value != NULL, FALSE);
+
+  if (!current_settings_initialized)
+    {
+      _gdk_macos_settings_load (&current_settings);
+      current_settings_initialized = TRUE;
+    }
+
+  if (FALSE) {}
+  else if (strcmp (setting, "gtk-enable-animations") == 0)
+    {
+      g_value_set_boolean (value, current_settings.enable_animations);
+      ret = TRUE;
+    }
+  else if (strcmp (setting, "gtk-xft-dpi") == 0)
+    {
+      g_value_set_int (value, current_settings.xft_dpi);
+      ret = TRUE;
+    }
+  else if (strcmp (setting, "gtk-cursor-blink-timeout") == 0)
+    {
+      g_value_set_int (value, current_settings.cursor_blink_timeout);
+      ret = TRUE;
+    }
+  else if (strcmp (setting, "gtk-double-click-time") == 0)
+    {
+      g_value_set_int (value, current_settings.double_click_time);
+      ret = TRUE;
+    }
+  else if (strcmp (setting, "gtk-font-name") == 0)
+    {
+      g_value_set_static_string (value, current_settings.font_name);
+      ret = TRUE;
+    }
+  else if (strcmp (setting, "gtk-primary-button-warps-slider") == 0)
+    {
+      g_value_set_boolean (value, current_settings.primary_button_warps_slider);
+      ret = TRUE;
+    }
+  else if (strcmp (setting, "gtk-shell-shows-desktop") == 0)
+    {
+      g_value_set_boolean (value, current_settings.shell_shows_desktop);
+      ret = TRUE;
+    }
+  else if (strcmp (setting, "gtk-shell-shows-menubar") == 0)
+    {
+      g_value_set_boolean (value, current_settings.shell_shows_menubar);
+      ret = TRUE;
+    }
+
+  GDK_END_MACOS_ALLOC_POOL;
+
+  return ret;
+}
+
+void
+_gdk_macos_display_reload_settings (GdkMacosDisplay *self)
+{
+  GdkMacosSettings old_settings;
+
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+
+  old_settings = current_settings;
+  _gdk_macos_settings_load (&current_settings);
+  current_settings_initialized = TRUE;
+
+  if (old_settings.xft_dpi != current_settings.xft_dpi)
+    gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-xft-dpi");
+
+  if (old_settings.double_click_time != current_settings.double_click_time)
+    gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-double-click-time");
+
+  if (old_settings.enable_animations != current_settings.enable_animations)
+    gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-enable-animations");
+
+  if (old_settings.font_name != current_settings.font_name)
+    gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-font-name");
+
+  if (old_settings.primary_button_warps_slider != current_settings.primary_button_warps_slider)
+    gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-primary-button-warps-slider");
+
+  if (old_settings.shell_shows_menubar != current_settings.shell_shows_menubar)
+    gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-shell-shows-menubar");
+
+  if (old_settings.shell_shows_desktop != current_settings.shell_shows_desktop)
+    gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-shell-shows-desktop");
+}
diff --git a/gdk/macos/gdkmacosdisplay-translate.c b/gdk/macos/gdkmacosdisplay-translate.c
new file mode 100644 (file)
index 0000000..8e86459
--- /dev/null
@@ -0,0 +1,1219 @@
+/*
+ * Copyright 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * Copyright 1998-2002 Tor Lillqvist
+ * Copyright 2005-2008 Imendio AB
+ * Copyright 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#import "GdkMacosWindow.h"
+#import "GdkMacosBaseView.h"
+
+#include "gdkmacosdisplay-private.h"
+#include "gdkmacoskeymap-private.h"
+#include "gdkmacossurface-private.h"
+
+#define GDK_MOD2_MASK (1 << 4)
+#define GRIP_WIDTH 15
+#define GRIP_HEIGHT 15
+#define GDK_LION_RESIZE 5
+
+static gboolean
+test_resize (NSEvent         *event,
+             GdkMacosSurface *surface,
+             int              x,
+             int              y)
+{
+  NSWindow *window;
+
+  g_assert (event != NULL);
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+
+  window = _gdk_macos_surface_get_native (surface);
+
+  /* Resizing from the resize indicator only begins if an NSLeftMouseButton
+   * event is received in the resizing area.
+   */
+  if ([event type] == NSEventTypeLeftMouseDown &&
+      [window showsResizeIndicator])
+    {
+      NSRect frame;
+
+      /* If the resize indicator is visible and the event is in the lower
+       * right 15x15 corner, we leave these events to Cocoa as to be
+       * handled as resize events.  Applications may have widgets in this
+       * area.  These will most likely be larger than 15x15 and for scroll
+       * bars there are also other means to move the scroll bar.  Since
+       * the resize indicator is the only way of resizing windows on Mac
+       * OS, it is too important to not make functional.
+       */
+      frame = [[window contentView] bounds];
+      if (x > frame.size.width - GRIP_WIDTH &&
+          x < frame.size.width &&
+          y > frame.size.height - GRIP_HEIGHT &&
+          y < frame.size.height)
+        return TRUE;
+     }
+
+  /* If we're on Lion and within 5 pixels of an edge, then assume that the
+   * user wants to resize, and return NULL to let Quartz get on with it.
+   * We check the selector isRestorable to see if we're on 10.7.  This
+   * extra check is in case the user starts dragging before GDK recognizes
+   * the grab.
+   *
+   * We perform this check for a button press of all buttons, because we
+   * do receive, for instance, a right mouse down event for a GDK surface
+   * for x-coordinate range [-3, 0], but we do not want to forward this
+   * into GDK. Forwarding such events into GDK will confuse the pointer
+   * window finding code, because there are no GdkSurfaces present in
+   * the range [-3, 0].
+   */
+  if (([event type] == NSEventTypeLeftMouseDown ||
+       [event type] == NSEventTypeRightMouseDown ||
+       [event type] == NSEventTypeOtherMouseDown))
+    {
+      if (x < GDK_LION_RESIZE ||
+          x > GDK_SURFACE (surface)->width - GDK_LION_RESIZE ||
+          y > GDK_SURFACE (surface)->height - GDK_LION_RESIZE)
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+static guint32
+get_time_from_ns_event (NSEvent *event)
+{
+  double time = [event timestamp];
+  /* cast via double->uint64 conversion to make sure that it is
+   * wrapped on 32-bit machines when it overflows
+   */
+  return (guint32) (guint64) (time * 1000.0);
+}
+
+static int
+get_mouse_button_from_ns_event (NSEvent *event)
+{
+  NSInteger button = [event buttonNumber];
+
+  switch (button)
+    {
+    case 0:
+      return 1;
+    case 1:
+      return 3;
+    case 2:
+      return 2;
+    default:
+      return button + 1;
+    }
+}
+
+static GdkModifierType
+get_mouse_button_modifiers_from_ns_buttons (NSUInteger nsbuttons)
+{
+  GdkModifierType modifiers = 0;
+
+  if (nsbuttons & (1 << 0))
+    modifiers |= GDK_BUTTON1_MASK;
+  if (nsbuttons & (1 << 1))
+    modifiers |= GDK_BUTTON3_MASK;
+  if (nsbuttons & (1 << 2))
+    modifiers |= GDK_BUTTON2_MASK;
+  if (nsbuttons & (1 << 3))
+    modifiers |= GDK_BUTTON4_MASK;
+  if (nsbuttons & (1 << 4))
+    modifiers |= GDK_BUTTON5_MASK;
+
+  return modifiers;
+}
+
+static GdkModifierType
+get_mouse_button_modifiers_from_ns_event (NSEvent *event)
+{
+  GdkModifierType state = 0;
+  int button;
+
+  /* This maps buttons 1 to 5 to GDK_BUTTON[1-5]_MASK */
+  button = get_mouse_button_from_ns_event (event);
+  if (button >= 1 && button <= 5)
+    state = (1 << (button + 7));
+
+  return state;
+}
+
+static GdkModifierType
+get_keyboard_modifiers_from_ns_flags (NSUInteger nsflags)
+{
+  GdkModifierType modifiers = 0;
+
+  if (nsflags & NSEventModifierFlagCapsLock)
+    modifiers |= GDK_LOCK_MASK;
+  if (nsflags & NSEventModifierFlagShift)
+    modifiers |= GDK_SHIFT_MASK;
+  if (nsflags & NSEventModifierFlagControl)
+    modifiers |= GDK_CONTROL_MASK;
+  if (nsflags & NSEventModifierFlagOption)
+    modifiers |= GDK_ALT_MASK;
+  if (nsflags & NSEventModifierFlagCommand)
+    modifiers |= GDK_MOD2_MASK;
+
+  return modifiers;
+}
+
+static GdkModifierType
+get_keyboard_modifiers_from_ns_event (NSEvent *nsevent)
+{
+  return get_keyboard_modifiers_from_ns_flags ([nsevent modifierFlags]);
+}
+
+GdkModifierType
+_gdk_macos_display_get_current_mouse_modifiers (GdkMacosDisplay *self)
+{
+  return get_mouse_button_modifiers_from_ns_buttons ([NSEvent pressedMouseButtons]);
+}
+
+GdkModifierType
+_gdk_macos_display_get_current_keyboard_modifiers (GdkMacosDisplay *self)
+{
+  return get_keyboard_modifiers_from_ns_flags ([NSEvent modifierFlags]);
+}
+
+static GdkEvent *
+fill_button_event (GdkMacosDisplay *display,
+                   GdkMacosSurface *surface,
+                   NSEvent         *nsevent,
+                   int              x,
+                   int              y)
+{
+  GdkSeat *seat;
+  GdkEventType type;
+  GdkModifierType state;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (display));
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+
+  /* Ignore button events outside the window coords */
+  if (x < 0 || x > GDK_SURFACE (surface)->width ||
+      y < 0 || y > GDK_SURFACE (surface)->height)
+    return NULL;
+
+  seat = gdk_display_get_default_seat (GDK_DISPLAY (display));
+  state = get_keyboard_modifiers_from_ns_event (nsevent) |
+         _gdk_macos_display_get_current_mouse_modifiers (display);
+
+  switch ((int)[nsevent type])
+    {
+    case NSEventTypeLeftMouseDown:
+    case NSEventTypeRightMouseDown:
+    case NSEventTypeOtherMouseDown:
+      type = GDK_BUTTON_PRESS;
+      state &= ~get_mouse_button_modifiers_from_ns_event (nsevent);
+      break;
+
+    case NSEventTypeLeftMouseUp:
+    case NSEventTypeRightMouseUp:
+    case NSEventTypeOtherMouseUp:
+      type = GDK_BUTTON_RELEASE;
+      state |= get_mouse_button_modifiers_from_ns_event (nsevent);
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+
+  return gdk_button_event_new (type,
+                               GDK_SURFACE (surface),
+                               gdk_seat_get_pointer (seat),
+                               NULL,
+                               NULL,
+                               get_time_from_ns_event (nsevent),
+                               state,
+                               get_mouse_button_from_ns_event (nsevent),
+                               x,
+                               y,
+                               NULL);
+}
+
+static GdkEvent *
+synthesize_crossing_event (GdkMacosDisplay *display,
+                           GdkMacosSurface *surface,
+                           NSEvent         *nsevent,
+                           int              x,
+                           int              y)
+{
+  GdkEventType event_type;
+  GdkModifierType state;
+  GdkSeat *seat;
+
+  switch ((int)[nsevent type])
+    {
+    case NSEventTypeMouseEntered:
+      event_type = GDK_ENTER_NOTIFY;
+      break;
+
+    case NSEventTypeMouseExited:
+      event_type = GDK_LEAVE_NOTIFY;
+      break;
+
+    default:
+      g_return_val_if_reached (NULL);
+    }
+
+  state = get_keyboard_modifiers_from_ns_event (nsevent) |
+         _gdk_macos_display_get_current_mouse_modifiers (display);
+  seat = gdk_display_get_default_seat (GDK_DISPLAY (display));
+
+  return gdk_crossing_event_new (event_type,
+                                 GDK_SURFACE (surface),
+                                 gdk_seat_get_pointer (seat),
+                                 NULL,
+                                 get_time_from_ns_event (nsevent),
+                                 state,
+                                 x,
+                                 y,
+                                 GDK_CROSSING_NORMAL,
+                                 GDK_NOTIFY_NONLINEAR);
+}
+
+static inline guint
+get_group_from_ns_event (NSEvent *nsevent)
+{
+  return ([nsevent modifierFlags] & NSEventModifierFlagOption) ? 1 : 0;
+}
+
+static void
+add_virtual_modifiers (GdkModifierType *state)
+{
+  if (*state & GDK_MOD2_MASK)
+    *state |= GDK_META_MASK;
+}
+
+static GdkEvent *
+fill_key_event (GdkMacosDisplay *display,
+                GdkMacosSurface *surface,
+                NSEvent         *nsevent,
+                GdkEventType     type)
+{
+  GdkTranslatedKey translated = {0};
+  GdkTranslatedKey no_lock = {0};
+  GdkModifierType consumed;
+  GdkModifierType state;
+  GdkKeymap *keymap;
+  gboolean is_modifier;
+  GdkSeat *seat;
+  guint keycode;
+  guint keyval;
+  guint group;
+  int layout;
+  int level;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (display));
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+  g_assert (nsevent != NULL);
+
+  seat = gdk_display_get_default_seat (GDK_DISPLAY (display));
+  keymap = gdk_display_get_keymap (GDK_DISPLAY (display));
+  keycode = [nsevent keyCode];
+  keyval = GDK_KEY_VoidSymbol;
+  state = get_keyboard_modifiers_from_ns_event (nsevent);
+  group = get_group_from_ns_event (nsevent);
+  is_modifier = _gdk_macos_keymap_is_modifier (keycode);
+
+  gdk_keymap_translate_keyboard_state (keymap, keycode, state, group,
+                                       &keyval, &layout, &level, &consumed);
+
+  /* If the key press is a modifier, the state should include the mask for
+   * that modifier but only for releases, not presses. This matches the
+   * X11 backend behavior.
+   */
+  if (is_modifier)
+    {
+      guint mask = 0;
+
+      switch (keyval)
+        {
+        case GDK_KEY_Meta_R:
+        case GDK_KEY_Meta_L:
+          mask = GDK_MOD2_MASK;
+          break;
+        case GDK_KEY_Shift_R:
+        case GDK_KEY_Shift_L:
+          mask = GDK_SHIFT_MASK;
+          break;
+        case GDK_KEY_Caps_Lock:
+          mask = GDK_LOCK_MASK;
+          break;
+        case GDK_KEY_Alt_R:
+        case GDK_KEY_Alt_L:
+          mask = GDK_ALT_MASK;
+          break;
+        case GDK_KEY_Control_R:
+        case GDK_KEY_Control_L:
+          mask = GDK_CONTROL_MASK;
+          break;
+        default:
+          mask = 0;
+        }
+
+      if (type == GDK_KEY_PRESS)
+        state &= ~mask;
+      else if (type == GDK_KEY_RELEASE)
+        state |= mask;
+    }
+
+  state |= _gdk_macos_display_get_current_mouse_modifiers (display);
+  add_virtual_modifiers (&state);
+
+  translated.keyval = keyval;
+  translated.consumed = consumed;
+  translated.layout = layout;
+  translated.level = level;
+
+  if (state & GDK_LOCK_MASK)
+    {
+      gdk_keymap_translate_keyboard_state (keymap,
+                                           keycode,
+                                           state & ~GDK_LOCK_MASK,
+                                           group,
+                                           &keyval,
+                                           &layout,
+                                           &level,
+                                           &consumed);
+
+      no_lock.keyval = keycode;
+      no_lock.consumed = consumed;
+      no_lock.layout = layout;
+      no_lock.level = level;
+    }
+  else
+    {
+      no_lock = translated;
+    }
+
+  return gdk_key_event_new (type,
+                            GDK_SURFACE (surface),
+                            gdk_seat_get_keyboard (seat),
+                            NULL,
+                            get_time_from_ns_event (nsevent),
+                            [nsevent keyCode],
+                            state,
+                            is_modifier,
+                            &translated,
+                            &no_lock);
+}
+
+static GdkEvent *
+fill_pinch_event (GdkMacosDisplay *display,
+                  GdkMacosSurface *surface,
+                  NSEvent         *nsevent,
+                  int              x,
+                  int              y)
+{
+  static double last_scale = 1.0;
+  static enum {
+    FP_STATE_IDLE,
+    FP_STATE_UPDATE
+  } last_state = FP_STATE_IDLE;
+  GdkSeat *seat;
+  GdkTouchpadGesturePhase phase;
+  gdouble angle_delta = 0.0;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (display));
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+
+  /* fill_pinch_event handles the conversion from the two OSX gesture events
+   * NSEventTypeMagnfiy and NSEventTypeRotate to the GDK_TOUCHPAD_PINCH event.
+   * The normal behavior of the OSX events is that they produce as sequence of
+   *   1 x NSEventPhaseBegan,
+   *   n x NSEventPhaseChanged,
+   *   1 x NSEventPhaseEnded
+   * This can happen for both the Magnify and the Rotate events independently.
+   * As both events are summarized in one GDK_TOUCHPAD_PINCH event sequence, a
+   * little state machine handles the case of two NSEventPhaseBegan events in
+   * a sequence, e.g. Magnify(Began), Magnify(Changed)..., Rotate(Began)...
+   * such that PINCH(STARTED), PINCH(UPDATE).... will not show a second
+   * PINCH(STARTED) event.
+   */
+
+  switch ((int)[nsevent phase])
+    {
+    case NSEventPhaseBegan:
+      switch (last_state)
+        {
+        case FP_STATE_IDLE:
+          phase = GDK_TOUCHPAD_GESTURE_PHASE_BEGIN;
+          last_state = FP_STATE_UPDATE;
+          last_scale = 1.0;
+          break;
+        case FP_STATE_UPDATE:
+          /* We have already received a PhaseBegan event but no PhaseEnded
+             event. This can happen, e.g. Magnify(Began), Magnify(Change)...
+             Rotate(Began), Rotate (Change),...., Magnify(End) Rotate(End)
+          */
+          phase = GDK_TOUCHPAD_GESTURE_PHASE_UPDATE;
+          break;
+        }
+      break;
+
+    case NSEventPhaseChanged:
+      phase = GDK_TOUCHPAD_GESTURE_PHASE_UPDATE;
+      break;
+
+    case NSEventPhaseEnded:
+      phase = GDK_TOUCHPAD_GESTURE_PHASE_END;
+      switch (last_state)
+        {
+        case FP_STATE_IDLE:
+          /* We are idle but have received a second PhaseEnded event.
+             This can happen because we have Magnify and Rotate OSX
+             event sequences. We just send a second end GDK_PHASE_END.
+          */
+          break;
+        case FP_STATE_UPDATE:
+          last_state = FP_STATE_IDLE;
+          break;
+        }
+      break;
+
+    case NSEventPhaseCancelled:
+      phase = GDK_TOUCHPAD_GESTURE_PHASE_CANCEL;
+      last_state = FP_STATE_IDLE;
+      break;
+
+    case NSEventPhaseMayBegin:
+    case NSEventPhaseStationary:
+      phase = GDK_TOUCHPAD_GESTURE_PHASE_CANCEL;
+      break;
+
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  switch ((int)[nsevent type])
+    {
+    case NSEventTypeMagnify:
+      last_scale *= [nsevent magnification] + 1.0;
+      angle_delta = 0.0;
+      break;
+
+    case NSEventTypeRotate:
+      angle_delta = - [nsevent rotation] * G_PI / 180.0;
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+
+  seat = gdk_display_get_default_seat (GDK_DISPLAY (display));
+
+  return gdk_touchpad_event_new_pinch (GDK_SURFACE (surface),
+                                       gdk_seat_get_pointer (seat),
+                                       NULL,
+                                       get_time_from_ns_event (nsevent),
+                                       get_keyboard_modifiers_from_ns_event (nsevent),
+                                       phase,
+                                       x,
+                                       y,
+                                       2,
+                                       0.0,
+                                       0.0,
+                                       last_scale,
+                                       angle_delta);
+
+}
+
+static gboolean
+is_motion_event (NSEventType event_type)
+{
+  return (event_type == NSEventTypeLeftMouseDragged ||
+          event_type == NSEventTypeRightMouseDragged ||
+          event_type == NSEventTypeOtherMouseDragged ||
+          event_type == NSEventTypeMouseMoved);
+}
+
+static GdkEvent *
+fill_motion_event (GdkMacosDisplay *display,
+                   GdkMacosSurface *surface,
+                   NSEvent         *nsevent,
+                   int              x,
+                   int              y)
+{
+  GdkSeat *seat;
+  GdkModifierType state;
+
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+  g_assert (nsevent != NULL);
+  g_assert (is_motion_event ([nsevent type]));
+
+  seat = gdk_display_get_default_seat (GDK_DISPLAY (display));
+  state = get_keyboard_modifiers_from_ns_event (nsevent) |
+          _gdk_macos_display_get_current_mouse_modifiers (display);
+
+  return gdk_motion_event_new (GDK_SURFACE (surface),
+                               gdk_seat_get_pointer (seat),
+                               NULL,
+                               NULL,
+                               get_time_from_ns_event (nsevent),
+                               state,
+                               x,
+                               y,
+                               NULL);
+}
+
+static GdkEvent *
+fill_scroll_event (GdkMacosDisplay *self,
+                   GdkMacosSurface *surface,
+                   NSEvent         *nsevent,
+                   int              x,
+                   int              y)
+{
+  GdkScrollDirection direction = 0;
+  GdkModifierType state;
+  GdkDevice *pointer;
+  GdkEvent *ret = NULL;
+  GdkSeat *seat;
+  gdouble dx;
+  gdouble dy;
+
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+  g_assert (nsevent != NULL);
+
+  seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
+  pointer = gdk_seat_get_pointer (seat);
+  state = _gdk_macos_display_get_current_mouse_modifiers (self) |
+          _gdk_macos_display_get_current_keyboard_modifiers (self);
+
+  dx = [nsevent deltaX];
+  dy = [nsevent deltaY];
+
+  if ([nsevent hasPreciseScrollingDeltas])
+    {
+      gdouble sx;
+      gdouble sy;
+
+      /*
+       * TODO: We probably need another event type for the
+       *       high precision scroll events since sx and dy
+       *       are in a unit we don't quite support. For now,
+       *       to slow it down multiply by .1.
+       */
+
+      sx = [nsevent scrollingDeltaX] * .1;
+      sy = [nsevent scrollingDeltaY] * .1;
+
+      if (sx != 0.0 || dx != 0.0)
+        ret = gdk_scroll_event_new (GDK_SURFACE (surface),
+                                    pointer,
+                                    NULL,
+                                    NULL,
+                                    get_time_from_ns_event (nsevent),
+                                    state,
+                                    -sx,
+                                    -sy,
+                                    FALSE);
+
+      /* Fall through for scroll emulation */
+    }
+
+  if (dy != 0.0)
+    {
+      if (dy < 0.0)
+        direction = GDK_SCROLL_DOWN;
+      else
+        direction = GDK_SCROLL_UP;
+
+      dx = 0.0;
+    }
+  else if (dx != 0.0)
+    {
+      if (dx < 0.0)
+        direction = GDK_SCROLL_RIGHT;
+      else
+        direction = GDK_SCROLL_LEFT;
+
+      dy = 0.0;
+    }
+
+  if (dx != 0.0 || dy != 0.0)
+    {
+      if ([nsevent hasPreciseScrollingDeltas])
+        {
+          GdkEvent *emulated;
+
+          emulated = gdk_scroll_event_new_discrete (GDK_SURFACE (surface),
+                                                    pointer,
+                                                    NULL,
+                                                    NULL,
+                                                    get_time_from_ns_event (nsevent),
+                                                    state,
+                                                    direction,
+                                                    TRUE);
+          _gdk_event_queue_append (GDK_DISPLAY (self), emulated);
+        }
+      else
+        {
+          g_assert (ret == NULL);
+
+          ret = gdk_scroll_event_new (GDK_SURFACE (surface),
+                                      pointer,
+                                      NULL,
+                                      NULL,
+                                      get_time_from_ns_event (nsevent),
+                                      state,
+                                      dx,
+                                      dy,
+                                      FALSE);
+        }
+    }
+
+  return g_steal_pointer (&ret);
+}
+
+static gboolean
+is_mouse_button_press_event (NSEventType type)
+{
+  switch ((int)type)
+    {
+    case NSEventTypeLeftMouseDown:
+    case NSEventTypeRightMouseDown:
+    case NSEventTypeOtherMouseDown:
+      return TRUE;
+
+    default:
+      return FALSE;
+    }
+}
+
+static void
+get_surface_point_from_screen_point (GdkSurface *surface,
+                                     NSPoint     screen_point,
+                                     int        *x,
+                                     int        *y)
+{
+  NSWindow *nswindow;
+  NSPoint point;
+
+  nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface));
+  point = [nswindow convertPointFromScreen:screen_point];
+
+  *x = point.x;
+  *y = surface->height - point.y;
+}
+
+static GdkSurface *
+find_surface_under_pointer (GdkMacosDisplay *self,
+                            NSPoint          screen_point,
+                            int             *x,
+                            int             *y)
+{
+  GdkPointerSurfaceInfo *info;
+  GdkSurface *surface;
+  GdkSeat *seat;
+  int x_tmp, y_tmp;
+
+  seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
+  info = _gdk_display_get_pointer_info (GDK_DISPLAY (self),
+                                        gdk_seat_get_pointer (seat));
+  surface = info->surface_under_pointer;
+
+  if (surface == NULL)
+    {
+      GdkMacosSurface *found;
+
+      found = _gdk_macos_display_get_surface_at_display_coords (self,
+                                                                screen_point.x,
+                                                                screen_point.y,
+                                                                &x_tmp, &y_tmp);
+
+      if (found)
+        {
+          surface = GDK_SURFACE (found);
+          info->surface_under_pointer = g_object_ref (surface);
+        }
+    }
+
+  if (surface)
+    {
+      _gdk_macos_display_from_display_coords (self,
+                                              screen_point.x,
+                                              screen_point.y,
+                                              &x_tmp, &y_tmp);
+      *x = x_tmp - GDK_MACOS_SURFACE (surface)->root_x;
+      *y = y_tmp - GDK_MACOS_SURFACE (surface)->root_y;
+      /* If the coordinates are out of window bounds, this surface is not
+       * under the pointer and we thus return NULL. This can occur when
+       * surface under pointer has not yet been updated due to a very recent
+       * window resize. Alternatively, we should no longer be relying on
+       * the surface_under_pointer value which is maintained in gdkwindow.c.
+       */
+      if (*x < 0 || *y < 0 || *x >= surface->width || *y >= surface->height)
+        return NULL;
+    }
+
+  return surface;
+}
+
+static GdkSurface *
+get_surface_from_ns_event (GdkMacosDisplay *self,
+                           NSEvent         *nsevent,
+                           NSPoint         *screen_point,
+                           int             *x,
+                           int             *y)
+{
+  GdkSurface *surface = NULL;
+  NSWindow *nswindow = [nsevent window];
+
+  if (nswindow)
+    {
+      GdkMacosBaseView *view;
+      NSPoint point, view_point;
+      NSRect view_frame;
+
+      view = (GdkMacosBaseView *)[nswindow contentView];
+      surface = GDK_SURFACE ([view gdkSurface]);
+
+      point = [nsevent locationInWindow];
+      view_point = [view convertPoint:point fromView:nil];
+      view_frame = [view frame];
+
+      /* NSEvents come in with a window set, but with window coordinates
+       * out of window bounds. For e.g. moved events this is fine, we use
+       * this information to properly handle enter/leave notify and motion
+       * events. For mouse button press/release, we want to avoid forwarding
+       * these events however, because the window they relate to is not the
+       * window set in the event. This situation appears to occur when button
+       * presses come in just before (or just after?) a window is resized and
+       * also when a button press occurs on the OS X window titlebar.
+       *
+       * By setting surface to NULL, we do another attempt to get the right
+       * surface window below.
+       */
+      if (is_mouse_button_press_event ([nsevent type]) &&
+          (view_point.x < view_frame.origin.x ||
+           view_point.x >= view_frame.origin.x + view_frame.size.width ||
+           view_point.y < view_frame.origin.y ||
+           view_point.y >= view_frame.origin.y + view_frame.size.height))
+        {
+          NSRect windowRect = [nswindow frame];
+
+          surface = NULL;
+
+          /* This is a hack for button presses to break all grabs. E.g. if
+           * a menu is open and one clicks on the title bar (or anywhere
+           * out of window bounds), we really want to pop down the menu (by
+           * breaking the grabs) before OS X handles the action of the title
+           * bar button.
+           *
+           * Because we cannot ingest this event into GDK, we have to do it
+           * here, not very nice.
+           */
+          _gdk_macos_display_break_all_grabs (self, get_time_from_ns_event (nsevent));
+
+          /* If the X,Y is on the frame itself, then we don't want to discover
+           * the surface under the pointer at all so that we let OS X handle
+           * it instead. We add padding to include resize operations too.
+           */
+          windowRect.origin.x = -GDK_LION_RESIZE;
+          windowRect.origin.y = -GDK_LION_RESIZE;
+          windowRect.size.width += (2 * GDK_LION_RESIZE);
+          windowRect.size.height += (2 * GDK_LION_RESIZE);
+          if (NSPointInRect (point, windowRect))
+            return NULL;
+        }
+      else
+        {
+          *screen_point = [(GdkMacosWindow *)[nsevent window] convertPointToScreen:point];
+          *x = point.x;
+          *y = surface->height - point.y;
+        }
+    }
+
+  if (!surface)
+    {
+      /* Fallback used when no NSSurface set.  This happens e.g. when
+       * we allow motion events without a window set in gdk_event_translate()
+       * that occur immediately after the main menu bar was clicked/used.
+       * This fallback will not return coordinates contained in a window's
+       * titlebar.
+       */
+      *screen_point = [NSEvent mouseLocation];
+      surface = find_surface_under_pointer (self, *screen_point, x, y);
+    }
+
+  return surface;
+}
+
+static GdkMacosSurface *
+find_surface_for_keyboard_event (NSEvent *nsevent)
+{
+  GdkMacosBaseView *view = (GdkMacosBaseView *)[[nsevent window] contentView];
+  GdkSurface *surface = GDK_SURFACE ([view gdkSurface]);
+  GdkDisplay *display = gdk_surface_get_display (surface);
+  GdkSeat *seat = gdk_display_get_default_seat (display);
+  GdkDevice *device = gdk_seat_get_keyboard (seat);
+  GdkDeviceGrabInfo *grab = _gdk_display_get_last_device_grab (display, device);
+
+  if (grab && grab->surface && !grab->owner_events)
+    return GDK_MACOS_SURFACE (grab->surface);
+
+  return GDK_MACOS_SURFACE (surface);
+}
+
+static GdkMacosSurface *
+find_surface_for_mouse_event (GdkMacosDisplay *self,
+                              NSEvent         *nsevent,
+                              int             *x,
+                              int             *y)
+{
+  NSPoint point;
+  NSEventType event_type;
+  GdkSurface *surface;
+  GdkDisplay *display;
+  GdkDevice *pointer;
+  GdkDeviceGrabInfo *grab;
+  GdkSeat *seat;
+
+  surface = get_surface_from_ns_event (self, nsevent, &point, x, y);
+  display = gdk_surface_get_display (surface);
+  seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
+  pointer = gdk_seat_get_pointer (seat);
+
+  event_type = [nsevent type];
+
+  /* From the docs for XGrabPointer:
+   *
+   * If owner_events is True and if a generated pointer event
+   * would normally be reported to this client, it is reported
+   * as usual. Otherwise, the event is reported with respect to
+   * the grab_window and is reported only if selected by
+   * event_mask. For either value of owner_events, unreported
+   * events are discarded.
+   */
+  if ((grab = _gdk_display_get_last_device_grab (display, pointer)))
+    {
+      if (grab->owner_events)
+        {
+          /* For owner events, we need to use the surface under the
+           * pointer, not the window from the NSEvent, since that is
+           * reported with respect to the key window, which could be
+           * wrong.
+           */
+          GdkSurface *surface_under_pointer;
+          int x_tmp, y_tmp;
+
+          surface_under_pointer = find_surface_under_pointer (self, point, &x_tmp, &y_tmp);
+          if (surface_under_pointer)
+            {
+              surface = surface_under_pointer;
+              *x = x_tmp;
+              *y = y_tmp;
+            }
+
+          return GDK_MACOS_SURFACE (surface);
+        }
+      else
+        {
+          /* Finally check the grab window. */
+          GdkSurface *grab_surface = grab->surface;
+          get_surface_point_from_screen_point (grab_surface, point, x, y);
+          return GDK_MACOS_SURFACE (grab_surface);
+        }
+
+      return NULL;
+    }
+  else
+    {
+      /* The non-grabbed case. */
+      GdkSurface *surface_under_pointer;
+      int x_tmp, y_tmp;
+
+      /* Ignore all events but mouse moved that might be on the title
+       * bar (above the content view). The reason is that otherwise
+       * gdk gets confused about getting e.g. button presses with no
+       * window (the title bar is not known to it).
+       */
+      if (event_type != NSEventTypeMouseMoved)
+        {
+          if (*y < 0)
+            return NULL;
+        }
+
+      /* As for owner events, we need to use the surface under the
+       * pointer, not the window from the NSEvent.
+       */
+      surface_under_pointer = find_surface_under_pointer (self, point, &x_tmp, &y_tmp);
+      if (surface_under_pointer != NULL)
+        {
+          surface = surface_under_pointer;
+          *x = x_tmp;
+          *y = y_tmp;
+        }
+
+      return GDK_MACOS_SURFACE (surface);
+    }
+
+  return NULL;
+}
+
+/* This function finds the correct window to send an event to, taking
+ * into account grabs, event propagation, and event masks.
+ */
+static GdkMacosSurface *
+find_surface_for_ns_event (GdkMacosDisplay *self,
+                           NSEvent         *nsevent,
+                           int             *x,
+                           int             *y)
+{
+  GdkMacosBaseView *view;
+  GdkSurface *surface;
+  NSPoint point;
+  int x_tmp;
+  int y_tmp;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+  g_assert (nsevent != NULL);
+  g_assert (x != NULL);
+  g_assert (y != NULL);
+
+  view = (GdkMacosBaseView *)[[nsevent window] contentView];
+
+  if (!(surface = get_surface_from_ns_event (self, nsevent, &point, x, y)))
+    return NULL;
+
+  _gdk_macos_display_from_display_coords (self, point.x, point.y, &x_tmp, &y_tmp);
+
+  switch ((int)[nsevent type])
+    {
+    case NSEventTypeLeftMouseDown:
+    case NSEventTypeRightMouseDown:
+    case NSEventTypeOtherMouseDown:
+    case NSEventTypeLeftMouseUp:
+    case NSEventTypeRightMouseUp:
+    case NSEventTypeOtherMouseUp:
+    case NSEventTypeLeftMouseDragged:
+    case NSEventTypeRightMouseDragged:
+    case NSEventTypeOtherMouseDragged:
+    case NSEventTypeMouseMoved:
+    case NSEventTypeScrollWheel:
+    case NSEventTypeMagnify:
+    case NSEventTypeRotate:
+      return find_surface_for_mouse_event (self, nsevent, x, y);
+
+    case NSEventTypeMouseEntered:
+    case NSEventTypeMouseExited:
+      /* Only handle our own entered/exited events, not the ones for the
+       * titlebar buttons.
+       */
+      if ([nsevent trackingArea] == [view trackingArea])
+        return GDK_MACOS_SURFACE (surface);
+      else
+        return NULL;
+
+    case NSEventTypeKeyDown:
+    case NSEventTypeKeyUp:
+    case NSEventTypeFlagsChanged:
+      return find_surface_for_keyboard_event (nsevent);
+
+    default:
+      /* Ignore everything else. */
+      return NULL;
+    }
+}
+
+GdkEvent *
+_gdk_macos_display_translate (GdkMacosDisplay *self,
+                              NSEvent         *nsevent)
+{
+  GdkMacosSurface *surface;
+  GdkMacosWindow *window;
+  NSEventType event_type;
+  GdkEvent *ret = NULL;
+  int x;
+  int y;
+
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), NULL);
+  g_return_val_if_fail (nsevent != NULL, NULL);
+
+  /* There is no support for real desktop wide grabs, so we break
+   * grabs when the application loses focus (gets deactivated).
+   */
+  event_type = [nsevent type];
+  if (event_type == NSEventTypeAppKitDefined)
+    {
+      if ([nsevent subtype] == NSEventSubtypeApplicationDeactivated)
+        _gdk_macos_display_break_all_grabs (self, get_time_from_ns_event (nsevent));
+
+      /* This could potentially be used to break grabs when clicking
+       * on the title. The subtype 20 is undocumented so it's probably
+       * not a good idea: else if (subtype == 20) break_all_grabs ();
+       */
+
+      /* Leave all AppKit events to AppKit. */
+      return NULL;
+    }
+
+  if (!(surface = find_surface_for_ns_event (self, nsevent, &x, &y)))
+    return NULL;
+
+  if (!(window = (GdkMacosWindow *)_gdk_macos_surface_get_native (surface)))
+    return NULL;
+
+  /* Ignore events and break grabs while the window is being
+   * dragged. This is a workaround for the window getting events for
+   * the window title.
+   */
+  if ([window isInMove])
+    {
+      _gdk_macos_display_break_all_grabs (self, get_time_from_ns_event (nsevent));
+      return NULL;
+    }
+
+  /* Also when in a manual resize or move , we ignore events so that
+   * these are pushed to GdkMacosNSWindow's sendEvent handler.
+   */
+  if ([window isInManualResizeOrMove])
+    return NULL;
+
+  /* Make sure we have a GdkSurface */
+  if (!(surface = [window gdkSurface]))
+    return NULL;
+
+  /* Quartz handles resizing on its own, so stay out of the way. */
+  if (test_resize (nsevent, surface, x, y))
+    return NULL;
+
+  if ((event_type == NSEventTypeRightMouseDown ||
+       event_type == NSEventTypeOtherMouseDown ||
+       event_type == NSEventTypeLeftMouseDown))
+    {
+      if (![NSApp isActive])
+        [NSApp activateIgnoringOtherApps:YES];
+
+      if (![window isKeyWindow])
+        [window makeKeyWindow];
+    }
+
+  switch ((int)event_type)
+    {
+    case NSEventTypeLeftMouseDown:
+    case NSEventTypeRightMouseDown:
+    case NSEventTypeOtherMouseDown:
+    case NSEventTypeLeftMouseUp:
+    case NSEventTypeRightMouseUp:
+    case NSEventTypeOtherMouseUp:
+      ret = fill_button_event (self, surface, nsevent, x, y);
+      break;
+
+    case NSEventTypeLeftMouseDragged:
+    case NSEventTypeRightMouseDragged:
+    case NSEventTypeOtherMouseDragged:
+    case NSEventTypeMouseMoved:
+      ret = fill_motion_event (self, surface, nsevent, x, y);
+      break;
+
+    case NSEventTypeMagnify:
+    case NSEventTypeRotate:
+      ret = fill_pinch_event (self, surface, nsevent, x, y);
+      break;
+
+    case NSEventTypeMouseExited:
+      [[NSCursor arrowCursor] set];
+      /* fallthrough */
+    case NSEventTypeMouseEntered:
+      ret = synthesize_crossing_event (self, surface, nsevent, x, y);
+      break;
+
+    case NSEventTypeKeyDown:
+    case NSEventTypeKeyUp:
+    case NSEventTypeFlagsChanged: {
+      GdkEventType type = _gdk_macos_keymap_get_event_type (nsevent);
+
+      if (type)
+        ret = fill_key_event (self, surface, nsevent, type);
+
+      break;
+    }
+
+    case NSEventTypeScrollWheel:
+      ret = fill_scroll_event (self, surface, nsevent, x, y);
+      break;
+
+    default:
+      break;
+    }
+
+  return ret;
+}
+
+void
+_gdk_macos_display_synthesize_motion (GdkMacosDisplay *self,
+                                      GdkMacosSurface *surface)
+{
+  GdkModifierType state;
+  GdkEvent *event;
+  GdkSeat *seat;
+  NSPoint point;
+  GList *node;
+  int x;
+  int y;
+
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
+
+  seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
+  point = [NSEvent mouseLocation];
+  _gdk_macos_display_from_display_coords (self, point.x, point.y, &x, &y);
+
+  state = _gdk_macos_display_get_current_keyboard_modifiers (self) |
+          _gdk_macos_display_get_current_mouse_modifiers (self);
+
+  event = gdk_motion_event_new (GDK_SURFACE (surface),
+                                gdk_seat_get_pointer (seat),
+                                NULL,
+                                NULL,
+                                get_time_from_ns_event ([NSApp currentEvent]),
+                                state,
+                                x,
+                                y,
+                                NULL);
+  node = _gdk_event_queue_append (GDK_DISPLAY (self), event);
+  _gdk_windowing_got_event (GDK_DISPLAY (self), node, event, 0);
+}
+
+void
+_gdk_macos_display_send_button_event (GdkMacosDisplay *self,
+                                      NSEvent         *nsevent)
+{
+  GdkMacosSurface *surface;
+  GdkEvent *event;
+  int x;
+  int y;
+
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+  g_return_if_fail (nsevent != NULL);
+
+  if ((surface = find_surface_for_ns_event (self, nsevent, &x, &y)) &&
+      (event = fill_button_event (self, surface, nsevent, x, y)))
+    _gdk_windowing_got_event (GDK_DISPLAY (self),
+                              _gdk_event_queue_append (GDK_DISPLAY (self), event),
+                              event,
+                              _gdk_display_get_next_serial (GDK_DISPLAY (self)));
+}
diff --git a/gdk/macos/gdkmacosdisplay.c b/gdk/macos/gdkmacosdisplay.c
new file mode 100644 (file)
index 0000000..800696e
--- /dev/null
@@ -0,0 +1,1071 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include <AppKit/AppKit.h>
+
+#import "GdkMacosWindow.h"
+
+#include "gdkdisplayprivate.h"
+#include "gdkeventsprivate.h"
+
+#include "gdkdisplaylinksource.h"
+#include "gdkmacosclipboard-private.h"
+#include "gdkmacoscairocontext-private.h"
+#include "gdkmacoseventsource-private.h"
+#include "gdkmacosdisplay-private.h"
+#include "gdkmacosglcontext-private.h"
+#include "gdkmacoskeymap-private.h"
+#include "gdkmacosmonitor-private.h"
+#include "gdkmacosseat-private.h"
+#include "gdkmacossurface-private.h"
+#include "gdkmacosutils-private.h"
+
+/**
+ * SECTION:macos_interaction
+ * @Short_description: macOS backend-specific functions
+ * @Title: macOS Interaction
+ * @Include: gdk/macos/gdkmacos.h
+ *
+ * The functions in this section are specific to the GDK macOS backend.
+ * To use them, you need to include the `<gdk/macos/gdkmacos.h>` header and
+ * use the macOS-specific pkg-config `gtk4-macos` file to build your
+ * application.
+ *
+ * To make your code compile with other GDK backends, guard backend-specific
+ * calls by an ifdef as follows. Since GDK may be built with multiple
+ * backends, you should also check for the backend that is in use (e.g. by
+ * using the GDK_IS_MACOS_DISPLAY() macro).
+ * |[<!-- language="C" -->
+ * #ifdef GDK_WINDOWING_MACOS
+ *   if (GDK_IS_MACOS_DISPLAY (display))
+ *     {
+ *       // make macOS-specific calls here
+ *     }
+ *   else
+ * #endif
+ * #ifdef GDK_WINDOWING_X11
+ *   if (GDK_IS_X11_DISPLAY (display))
+ *     {
+ *       // make X11-specific calls here
+ *     }
+ *   else
+ * #endif
+ *   g_error ("Unsupported GDK backend");
+ * ]|
+ */
+
+G_DEFINE_TYPE (GdkMacosDisplay, gdk_macos_display, GDK_TYPE_DISPLAY)
+
+static GSource *event_source;
+
+static GdkMacosMonitor *
+get_monitor (GdkMacosDisplay *self,
+             guint            position)
+{
+  GdkMacosMonitor *monitor;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+
+  /* Get the monitor but return a borrowed reference */
+  monitor = g_list_model_get_item (G_LIST_MODEL (self->monitors), position);
+  if (monitor != NULL)
+    g_object_unref (monitor);
+
+  return monitor;
+}
+
+static gboolean
+gdk_macos_display_get_setting (GdkDisplay  *display,
+                               const gchar *setting,
+                               GValue      *value)
+{
+  return _gdk_macos_display_get_setting (GDK_MACOS_DISPLAY (display), setting, value);
+}
+
+static GListModel *
+gdk_macos_display_get_monitors (GdkDisplay *display)
+{
+  return G_LIST_MODEL (GDK_MACOS_DISPLAY (display)->monitors);
+}
+
+static GdkMonitor *
+gdk_macos_display_get_monitor_at_surface (GdkDisplay *display,
+                                          GdkSurface *surface)
+{
+  GdkMacosDisplay *self = (GdkMacosDisplay *)display;
+  CGDirectDisplayID screen_id;
+  guint n_monitors;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+
+  screen_id = _gdk_macos_surface_get_screen_id (GDK_MACOS_SURFACE (surface));
+  n_monitors = g_list_model_get_n_items (G_LIST_MODEL (self->monitors));
+
+  for (guint i = 0; i < n_monitors; i++)
+    {
+      GdkMacosMonitor *monitor = get_monitor (self, i);
+
+      if (screen_id == _gdk_macos_monitor_get_screen_id (monitor))
+        return GDK_MONITOR (monitor);
+    }
+
+  return GDK_MONITOR (get_monitor (self, 0));
+}
+
+static GdkMacosMonitor *
+gdk_macos_display_find_monitor (GdkMacosDisplay   *self,
+                                CGDirectDisplayID  screen_id)
+{
+  guint n_monitors;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+
+  n_monitors = g_list_model_get_n_items (G_LIST_MODEL (self->monitors));
+
+  for (guint i = 0; i < n_monitors; i++)
+    {
+      GdkMacosMonitor *monitor = get_monitor (self, i);
+
+      if (screen_id == _gdk_macos_monitor_get_screen_id (monitor))
+        return monitor;
+    }
+
+  return NULL;
+}
+
+static void
+gdk_macos_display_update_bounds (GdkMacosDisplay *self)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+
+  self->min_x = G_MAXINT;
+  self->min_y = G_MAXINT;
+
+  self->max_x = G_MININT;
+  self->max_y = G_MININT;
+
+  for (id obj in [NSScreen screens])
+    {
+      NSRect geom = [(NSScreen *)obj frame];
+
+      self->min_x = MIN (self->min_x, geom.origin.x);
+      self->min_y = MIN (self->min_y, geom.origin.y);
+      self->max_x = MAX (self->max_x, geom.origin.x + geom.size.width);
+      self->max_y = MAX (self->max_y, geom.origin.y + geom.size.height);
+    }
+
+  self->width = self->max_x - self->min_x;
+  self->height = self->max_y - self->min_y;
+
+  GDK_END_MACOS_ALLOC_POOL;
+}
+
+static void
+gdk_macos_display_monitors_changed_cb (CFNotificationCenterRef  center,
+                                       void                    *observer,
+                                       CFStringRef              name,
+                                       const void              *object,
+                                       CFDictionaryRef          userInfo)
+{
+  GdkMacosDisplay *self = observer;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+
+  _gdk_macos_display_reload_monitors (self);
+
+  /* Now we need to update all our surface positions since they
+   * probably just changed origins. We ignore the popup surfaces
+   * since we can rely on the toplevel surfaces to handle that.
+   */
+  for (const GList *iter = _gdk_macos_display_get_surfaces (self);
+       iter != NULL;
+       iter = iter->next)
+    {
+      GdkMacosSurface *surface = iter->data;
+
+      g_assert (GDK_IS_MACOS_SURFACE (surface));
+
+      if (GDK_IS_TOPLEVEL (surface))
+        _gdk_macos_surface_update_position (surface);
+    }
+}
+
+static void
+gdk_macos_display_user_defaults_changed_cb (CFNotificationCenterRef  center,
+                                            void                    *observer,
+                                            CFStringRef              name,
+                                            const void              *object,
+                                            CFDictionaryRef          userInfo)
+{
+  GdkMacosDisplay *self = observer;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+
+  _gdk_macos_display_reload_settings (self);
+}
+
+void
+_gdk_macos_display_reload_monitors (GdkMacosDisplay *self)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  GArray *seen;
+  guint n_monitors;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+
+  gdk_macos_display_update_bounds (self);
+
+  seen = g_array_new (FALSE, FALSE, sizeof (CGDirectDisplayID));
+
+  for (id obj in [NSScreen screens])
+    {
+      CGDirectDisplayID screen_id;
+      GdkMacosMonitor *monitor;
+
+      screen_id = [[[obj deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
+      g_array_append_val (seen, screen_id);
+
+      if ((monitor = gdk_macos_display_find_monitor (self, screen_id)))
+        {
+          _gdk_macos_monitor_reconfigure (monitor);
+        }
+      else
+        {
+          monitor = _gdk_macos_monitor_new (self, screen_id);
+          g_list_store_append (self->monitors, monitor);
+          g_object_unref (monitor);
+        }
+    }
+
+  n_monitors = g_list_model_get_n_items (G_LIST_MODEL (self->monitors));
+
+  for (guint i = n_monitors; i > 0; i--)
+    {
+      GdkMacosMonitor *monitor = get_monitor (self, i - 1);
+      CGDirectDisplayID screen_id = _gdk_macos_monitor_get_screen_id (monitor);
+      gboolean found = FALSE;
+
+      for (guint j = 0; j < seen->len; j++)
+        {
+          if (screen_id == g_array_index (seen, CGDirectDisplayID, j))
+            {
+              found = TRUE;
+              break;
+            }
+        }
+
+      if (!found)
+        g_list_store_remove (self->monitors, i - 1);
+    }
+
+  g_array_unref (seen);
+
+  GDK_END_MACOS_ALLOC_POOL;
+}
+
+static void
+gdk_macos_display_load_seat (GdkMacosDisplay *self)
+{
+  GdkSeat *seat;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+
+  seat = _gdk_macos_seat_new (self);
+  gdk_display_add_seat (GDK_DISPLAY (self), seat);
+  g_object_unref (seat);
+}
+
+static gboolean
+gdk_macos_display_frame_cb (gpointer data)
+{
+  GdkMacosDisplay *self = data;
+  GdkDisplayLinkSource *source;
+  gint64 presentation_time;
+  gint64 now;
+  GList *iter;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+
+  source = (GdkDisplayLinkSource *)self->frame_source;
+
+  presentation_time = source->presentation_time;
+  now = g_source_get_time ((GSource *)source);
+
+  iter = self->awaiting_frames.head;
+
+  while (iter != NULL)
+    {
+      GdkMacosSurface *surface = iter->data;
+
+      g_assert (GDK_IS_MACOS_SURFACE (surface));
+
+      iter = iter->next;
+
+      _gdk_macos_display_remove_frame_callback (self, surface);
+      _gdk_macos_surface_thaw (surface,
+                               source->presentation_time,
+                               source->refresh_interval);
+    }
+
+  return G_SOURCE_CONTINUE;
+}
+
+static void
+gdk_macos_display_load_display_link (GdkMacosDisplay *self)
+{
+  self->frame_source = gdk_display_link_source_new ();
+  g_source_set_callback (self->frame_source,
+                         gdk_macos_display_frame_cb,
+                         self,
+                         NULL);
+  g_source_attach (self->frame_source, NULL);
+}
+
+static const gchar *
+gdk_macos_display_get_name (GdkDisplay *display)
+{
+  return GDK_MACOS_DISPLAY (display)->name;
+}
+
+static void
+gdk_macos_display_beep (GdkDisplay *display)
+{
+  NSBeep ();
+}
+
+static void
+gdk_macos_display_flush (GdkDisplay *display)
+{
+  /* Not Supported */
+}
+
+static void
+gdk_macos_display_sync (GdkDisplay *display)
+{
+  /* Not Supported */
+}
+
+static gulong
+gdk_macos_display_get_next_serial (GdkDisplay *display)
+{
+  return 0;
+}
+
+static gboolean
+gdk_macos_display_has_pending (GdkDisplay *display)
+{
+  return _gdk_event_queue_find_first (display) ||
+         _gdk_macos_event_source_check_pending ();
+}
+
+static void
+gdk_macos_display_notify_startup_complete (GdkDisplay  *display,
+                                           const gchar *startup_notification_id)
+{
+  /* Not Supported */
+}
+
+static void
+gdk_macos_display_queue_events (GdkDisplay *display)
+{
+  GdkMacosDisplay *self = (GdkMacosDisplay *)display;
+  NSEvent *nsevent;
+
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+
+  if ((nsevent = _gdk_macos_event_source_get_pending ()))
+    {
+      GdkEvent *event = _gdk_macos_display_translate (self, nsevent);
+
+      if (event != NULL)
+        _gdk_windowing_got_event (GDK_DISPLAY (self),
+                                  _gdk_event_queue_append (GDK_DISPLAY (self), event),
+                                  event,
+                                  0);
+      else
+        [NSApp sendEvent:nsevent];
+
+      [nsevent release];
+    }
+}
+
+static void
+_gdk_macos_display_surface_added (GdkMacosDisplay *self,
+                                  GdkMacosSurface *surface)
+{
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+  g_assert (!queue_contains (&self->sorted_surfaces, &surface->sorted));
+  g_assert (!queue_contains (&self->main_surfaces, &surface->main));
+  g_assert (!queue_contains (&self->awaiting_frames, &surface->frame));
+  g_assert (surface->sorted.data == surface);
+  g_assert (surface->main.data == surface);
+  g_assert (surface->frame.data == surface);
+
+  if (GDK_IS_TOPLEVEL (surface))
+    g_queue_push_tail_link (&self->main_surfaces, &surface->main);
+
+  _gdk_macos_display_clear_sorting (self);
+}
+
+void
+_gdk_macos_display_surface_removed (GdkMacosDisplay *self,
+                                    GdkMacosSurface *surface)
+{
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
+
+  if (self->keyboard_surface == surface)
+    _gdk_macos_display_surface_resigned_key (self, surface);
+
+  g_queue_unlink (&self->sorted_surfaces, &surface->sorted);
+
+  if (queue_contains (&self->main_surfaces, &surface->main))
+    _gdk_macos_display_surface_resigned_main (self, surface);
+
+  if (queue_contains (&self->awaiting_frames, &surface->frame))
+    g_queue_unlink (&self->awaiting_frames, &surface->frame);
+
+  g_return_if_fail (self->keyboard_surface != surface);
+}
+
+void
+_gdk_macos_display_surface_became_key (GdkMacosDisplay *self,
+                                       GdkMacosSurface *surface)
+{
+  GdkDevice *keyboard;
+  GdkEvent *event;
+  GdkSeat *seat;
+
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
+  g_return_if_fail (self->keyboard_surface == NULL);
+
+  self->keyboard_surface = surface;
+
+  seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
+  keyboard = gdk_seat_get_keyboard (seat);
+  event = gdk_focus_event_new (GDK_SURFACE (surface), keyboard, NULL, TRUE);
+  _gdk_event_queue_append (GDK_DISPLAY (self), event);
+
+  /* We just became the active window.  Unlike X11, Mac OS X does
+   * not send us motion events while the window does not have focus
+   * ("is not key").  We send a dummy motion notify event now, so that
+   * everything in the window is set to correct state.
+   */
+  _gdk_macos_display_synthesize_motion (self, surface);
+}
+
+void
+_gdk_macos_display_surface_resigned_key (GdkMacosDisplay *self,
+                                         GdkMacosSurface *surface)
+{
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
+
+  if (self->keyboard_surface == surface)
+    {
+      GdkDevice *keyboard;
+      GdkEvent *event;
+      GdkSeat *seat;
+
+      seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
+      keyboard = gdk_seat_get_keyboard (seat);
+      event = gdk_focus_event_new (GDK_SURFACE (surface), keyboard, NULL, FALSE);
+      _gdk_event_queue_append (GDK_DISPLAY (self), event);
+    }
+
+  self->keyboard_surface = NULL;
+
+  _gdk_macos_display_clear_sorting (self);
+}
+
+void
+_gdk_macos_display_surface_became_main (GdkMacosDisplay *self,
+                                        GdkMacosSurface *surface)
+{
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
+
+  if (queue_contains (&self->main_surfaces, &surface->main))
+    g_queue_unlink (&self->main_surfaces, &surface->main);
+
+  g_queue_push_head_link (&self->main_surfaces, &surface->main);
+
+  _gdk_macos_display_clear_sorting (self);
+}
+
+void
+_gdk_macos_display_surface_resigned_main (GdkMacosDisplay *self,
+                                          GdkMacosSurface *surface)
+{
+  GdkMacosSurface *new_surface = NULL;
+
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
+
+  if (queue_contains (&self->main_surfaces, &surface->main))
+    g_queue_unlink (&self->main_surfaces, &surface->main);
+
+  _gdk_macos_display_clear_sorting (self);
+
+  if (GDK_SURFACE (surface)->transient_for &&
+      gdk_surface_get_mapped (GDK_SURFACE (surface)->transient_for))
+    {
+      new_surface = GDK_MACOS_SURFACE (GDK_SURFACE (surface)->transient_for);
+    }
+  else
+    {
+      const GList *surfaces = _gdk_macos_display_get_surfaces (self);
+
+      for (const GList *iter = surfaces; iter; iter = iter->next)
+        {
+          GdkMacosSurface *item = iter->data;
+
+          g_assert (GDK_IS_MACOS_SURFACE (item));
+
+          if (item == surface)
+            continue;
+
+          if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (item)))
+            {
+              new_surface = item;
+              break;
+            }
+        }
+    }
+
+  if (new_surface != NULL)
+    {
+      NSWindow *nswindow = _gdk_macos_surface_get_native (new_surface);
+      [nswindow makeKeyAndOrderFront:nswindow];
+    }
+
+  _gdk_macos_display_clear_sorting (self);
+}
+
+static GdkSurface *
+gdk_macos_display_create_surface (GdkDisplay     *display,
+                                  GdkSurfaceType  surface_type,
+                                  GdkSurface     *parent,
+                                  int             x,
+                                  int             y,
+                                  int             width,
+                                  int             height)
+{
+  GdkMacosDisplay *self = (GdkMacosDisplay *)display;
+  GdkMacosSurface *surface;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+  g_assert (!parent || GDK_IS_MACOS_SURFACE (parent));
+
+  surface = _gdk_macos_surface_new (self, surface_type, parent, x, y, width, height);
+
+  if (surface != NULL)
+    _gdk_macos_display_surface_added (self, surface);
+
+  return GDK_SURFACE (surface);
+}
+
+static GdkKeymap *
+gdk_macos_display_get_keymap (GdkDisplay *display)
+{
+  GdkMacosDisplay *self = (GdkMacosDisplay *)display;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+
+  return GDK_KEYMAP (self->keymap);
+}
+
+static void
+gdk_macos_display_load_clipboard (GdkMacosDisplay *self)
+{
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+
+  GDK_DISPLAY (self)->clipboard = _gdk_macos_clipboard_new (self);
+}
+
+static gboolean
+gdk_macos_display_make_gl_context_current (GdkDisplay   *display,
+                                           GdkGLContext *gl_context)
+{
+  g_assert (GDK_IS_MACOS_DISPLAY (display));
+  g_assert (GDK_IS_MACOS_GL_CONTEXT (gl_context));
+
+  return _gdk_macos_gl_context_make_current (GDK_MACOS_GL_CONTEXT (gl_context));
+}
+
+static void
+gdk_macos_display_finalize (GObject *object)
+{
+  GdkMacosDisplay *self = (GdkMacosDisplay *)object;
+
+  CFNotificationCenterRemoveObserver (CFNotificationCenterGetDistributedCenter (),
+                                      self,
+                                      CFSTR ("NSApplicationDidChangeScreenParametersNotification"),
+                                      NULL);
+
+  CFNotificationCenterRemoveObserver (CFNotificationCenterGetDistributedCenter (),
+                                      self,
+                                      CFSTR ("NSUserDefaultsDidChangeNotification"),
+                                      NULL);
+
+  g_clear_object (&GDK_DISPLAY (self)->clipboard);
+  g_clear_pointer (&self->frame_source, g_source_unref);
+  g_clear_object (&self->monitors);
+  g_clear_pointer (&self->name, g_free);
+
+  G_OBJECT_CLASS (gdk_macos_display_parent_class)->finalize (object);
+}
+
+static void
+gdk_macos_display_class_init (GdkMacosDisplayClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkDisplayClass *display_class = GDK_DISPLAY_CLASS (klass);
+
+  object_class->finalize = gdk_macos_display_finalize;
+
+  display_class->cairo_context_type = GDK_TYPE_MACOS_CAIRO_CONTEXT;
+
+  display_class->beep = gdk_macos_display_beep;
+  display_class->create_surface = gdk_macos_display_create_surface;
+  display_class->flush = gdk_macos_display_flush;
+  display_class->get_keymap = gdk_macos_display_get_keymap;
+  display_class->get_monitors = gdk_macos_display_get_monitors;
+  display_class->get_monitor_at_surface = gdk_macos_display_get_monitor_at_surface;
+  display_class->get_next_serial = gdk_macos_display_get_next_serial;
+  display_class->get_name = gdk_macos_display_get_name;
+  display_class->get_setting = gdk_macos_display_get_setting;
+  display_class->has_pending = gdk_macos_display_has_pending;
+  display_class->make_gl_context_current = gdk_macos_display_make_gl_context_current;
+  display_class->notify_startup_complete = gdk_macos_display_notify_startup_complete;
+  display_class->queue_events = gdk_macos_display_queue_events;
+  display_class->sync = gdk_macos_display_sync;
+}
+
+static void
+gdk_macos_display_init (GdkMacosDisplay *self)
+{
+  self->monitors = g_list_store_new (GDK_TYPE_MONITOR);
+
+  gdk_display_set_composited (GDK_DISPLAY (self), TRUE);
+  gdk_display_set_input_shapes (GDK_DISPLAY (self), FALSE);
+  gdk_display_set_rgba (GDK_DISPLAY (self), TRUE);
+}
+
+GdkDisplay *
+_gdk_macos_display_open (const gchar *display_name)
+{
+  static GdkMacosDisplay *self;
+  ProcessSerialNumber psn = { 0, kCurrentProcess };
+
+  /* Until we can have multiple GdkMacosEventSource instances
+   * running concurrently, we can't exactly support multiple
+   * display connections. So just short-circuit if we already
+   * have one active.
+   */
+  if (self != NULL)
+    return NULL;
+
+  GDK_NOTE (MISC, g_message ("opening display %s", display_name ? display_name : ""));
+
+  /* Make the current process a foreground application, i.e. an app
+   * with a user interface, in case we're not running from a .app bundle
+   */
+  TransformProcessType (&psn, kProcessTransformToForegroundApplication);
+
+  [NSApplication sharedApplication];
+
+  self = g_object_new (GDK_TYPE_MACOS_DISPLAY, NULL);
+  self->name = g_strdup (display_name);
+  self->keymap = _gdk_macos_keymap_new (self);
+
+  gdk_macos_display_load_seat (self);
+  gdk_macos_display_load_clipboard (self);
+
+  /* Load CVDisplayLink before monitors to access refresh rates */
+  gdk_macos_display_load_display_link (self);
+  _gdk_macos_display_reload_monitors (self);
+
+  CFNotificationCenterAddObserver (CFNotificationCenterGetLocalCenter (),
+                                   self,
+                                   gdk_macos_display_monitors_changed_cb,
+                                   CFSTR ("NSApplicationDidChangeScreenParametersNotification"),
+                                   NULL,
+                                   CFNotificationSuspensionBehaviorDeliverImmediately);
+
+  CFNotificationCenterAddObserver (CFNotificationCenterGetDistributedCenter (),
+                                   self,
+                                   gdk_macos_display_user_defaults_changed_cb,
+                                   CFSTR ("NSUserDefaultsDidChangeNotification"),
+                                   NULL,
+                                   CFNotificationSuspensionBehaviorDeliverImmediately);
+
+  if (event_source == NULL)
+    {
+      event_source = _gdk_macos_event_source_new (self);
+      g_source_attach (event_source, NULL);
+    }
+
+  g_object_add_weak_pointer (G_OBJECT (self), (gpointer *)&self);
+
+  gdk_display_emit_opened (GDK_DISPLAY (self));
+
+  return GDK_DISPLAY (self);
+}
+
+void
+_gdk_macos_display_to_display_coords (GdkMacosDisplay *self,
+                                      int              x,
+                                      int              y,
+                                      int             *out_x,
+                                      int             *out_y)
+{
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+
+  if (out_y)
+    *out_y = self->height - y + self->min_y;
+
+  if (out_x)
+    *out_x = x + self->min_x;
+}
+
+void
+_gdk_macos_display_from_display_coords (GdkMacosDisplay *self,
+                                        int              x,
+                                        int              y,
+                                        int             *out_x,
+                                        int             *out_y)
+{
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+
+  if (out_y != NULL)
+    *out_y = self->height - y + self->min_y;
+
+  if (out_x != NULL)
+    *out_x = x - self->min_x;
+}
+
+GdkMonitor *
+_gdk_macos_display_get_monitor_at_coords (GdkMacosDisplay *self,
+                                          int              x,
+                                          int              y)
+{
+  guint n_monitors;
+
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), NULL);
+
+  n_monitors = g_list_model_get_n_items (G_LIST_MODEL (self->monitors));
+
+  for (guint i = 0; i < n_monitors; i++)
+    {
+      GdkMacosMonitor *monitor = get_monitor (self, i);
+
+      if (gdk_rectangle_contains_point (&GDK_MONITOR (monitor)->geometry, x, y))
+        return GDK_MONITOR (monitor);
+    }
+
+  return NULL;
+}
+
+GdkMonitor *
+_gdk_macos_display_get_monitor_at_display_coords (GdkMacosDisplay *self,
+                                                  int              x,
+                                                  int              y)
+{
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), NULL);
+
+  _gdk_macos_display_from_display_coords (self, x, y, &x, &y);
+
+  return _gdk_macos_display_get_monitor_at_coords (self, x, y);
+}
+
+NSScreen *
+_gdk_macos_display_get_screen_at_display_coords (GdkMacosDisplay *self,
+                                                 int              x,
+                                                 int              y)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  NSArray *screens;
+  NSScreen *screen = NULL;
+
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), NULL);
+
+  screens = [NSScreen screens];
+
+  for (id obj in screens)
+    {
+      NSRect geom = [obj frame];
+
+      if (x >= geom.origin.x && x <= geom.origin.x + geom.size.width &&
+          y >= geom.origin.y && y <= geom.origin.y + geom.size.height)
+        {
+          screen = obj;
+          break;
+        }
+    }
+
+  GDK_END_MACOS_ALLOC_POOL;
+
+  return screen;
+}
+
+void
+_gdk_macos_display_break_all_grabs (GdkMacosDisplay *self,
+                                    guint32          time)
+{
+  GdkDevice *devices[2];
+  GdkSeat *seat;
+
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+
+  seat = gdk_display_get_default_seat (GDK_DISPLAY (self));
+  devices[0] = gdk_seat_get_keyboard (seat);
+  devices[1] = gdk_seat_get_pointer (seat);
+
+  for (guint i = 0; i < G_N_ELEMENTS (devices); i++)
+    {
+      GdkDevice *device = devices[i];
+      GdkDeviceGrabInfo *grab;
+
+      grab = _gdk_display_get_last_device_grab (GDK_DISPLAY (self), device);
+
+      if (grab != NULL)
+        {
+          GdkEvent *event;
+          GList *node;
+
+          event = gdk_grab_broken_event_new (grab->surface,
+                                             device,
+                                             NULL,
+                                             grab->surface,
+                                             TRUE);
+          node = _gdk_event_queue_append (GDK_DISPLAY (self), event);
+          _gdk_windowing_got_event (GDK_DISPLAY (self), node, event, 0);
+        }
+    }
+}
+
+void
+_gdk_macos_display_queue_events (GdkMacosDisplay *self)
+{
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+
+  gdk_macos_display_queue_events (GDK_DISPLAY (self));
+}
+
+static GdkMacosSurface *
+_gdk_macos_display_get_surface_at_coords (GdkMacosDisplay *self,
+                                          int              x,
+                                          int              y,
+                                          int             *surface_x,
+                                          int             *surface_y)
+{
+  const GList *surfaces;
+
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), NULL);
+  g_return_val_if_fail (surface_x != NULL, NULL);
+  g_return_val_if_fail (surface_y != NULL, NULL);
+
+  surfaces = _gdk_macos_display_get_surfaces (self);
+
+  for (const GList *iter = surfaces; iter; iter = iter->next)
+    {
+      GdkSurface *surface = iter->data;
+      NSWindow *nswindow;
+
+      g_assert (GDK_IS_MACOS_SURFACE (surface));
+
+      if (!gdk_surface_get_mapped (surface))
+        continue;
+
+      nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface));
+
+      if (x >= GDK_MACOS_SURFACE (surface)->root_x &&
+          y >= GDK_MACOS_SURFACE (surface)->root_y &&
+          x <= (GDK_MACOS_SURFACE (surface)->root_x + surface->width) &&
+          y <= (GDK_MACOS_SURFACE (surface)->root_y + surface->height))
+        {
+          *surface_x = x - GDK_MACOS_SURFACE (surface)->root_x;
+          *surface_y = y - GDK_MACOS_SURFACE (surface)->root_y;
+
+          return GDK_MACOS_SURFACE (surface);
+        }
+    }
+
+  *surface_x = 0;
+  *surface_y = 0;
+
+  return NULL;
+}
+
+GdkMacosSurface *
+_gdk_macos_display_get_surface_at_display_coords (GdkMacosDisplay *self,
+                                                  double           x,
+                                                  double           y,
+                                                  int             *surface_x,
+                                                  int             *surface_y)
+{
+  int x_gdk;
+  int y_gdk;
+
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), NULL);
+  g_return_val_if_fail (surface_x != NULL, NULL);
+  g_return_val_if_fail (surface_y != NULL, NULL);
+
+  _gdk_macos_display_from_display_coords (self, x, y, &x_gdk, &y_gdk);
+
+  return _gdk_macos_display_get_surface_at_coords (self, x_gdk, y_gdk, surface_x, surface_y);
+}
+
+void
+_gdk_macos_display_add_frame_callback (GdkMacosDisplay *self,
+                                       GdkMacosSurface *surface)
+{
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
+
+  if (!queue_contains (&self->awaiting_frames, &surface->frame))
+    {
+      g_queue_push_tail_link (&self->awaiting_frames, &surface->frame);
+
+      if (self->awaiting_frames.length == 1)
+        gdk_display_link_source_unpause ((GdkDisplayLinkSource *)self->frame_source);
+    }
+}
+
+void
+_gdk_macos_display_remove_frame_callback (GdkMacosDisplay *self,
+                                          GdkMacosSurface *surface)
+{
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
+
+  if (queue_contains (&self->awaiting_frames, &surface->frame))
+    {
+      g_queue_unlink (&self->awaiting_frames, &surface->frame);
+
+      if (self->awaiting_frames.length == 0)
+        gdk_display_link_source_pause ((GdkDisplayLinkSource *)self->frame_source);
+    }
+}
+
+NSWindow *
+_gdk_macos_display_find_native_under_pointer (GdkMacosDisplay *self,
+                                              int             *x,
+                                              int             *y)
+{
+  GdkMacosSurface *surface;
+  NSPoint point;
+
+  g_assert (GDK_IS_MACOS_DISPLAY (self));
+
+  point = [NSEvent mouseLocation];
+
+  surface = _gdk_macos_display_get_surface_at_display_coords (self, point.x, point.y, x, y);
+  if (surface != NULL)
+    return _gdk_macos_surface_get_native (surface);
+
+  return NULL;
+}
+
+int
+_gdk_macos_display_get_nominal_refresh_rate (GdkMacosDisplay *self)
+{
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), 60 * 1000);
+
+  if (self->frame_source == NULL)
+    return 60 * 1000;
+
+  return ((GdkDisplayLinkSource *)self->frame_source)->refresh_rate;
+}
+
+void
+_gdk_macos_display_clear_sorting (GdkMacosDisplay *self)
+{
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+
+  self->sorted_surfaces.head = NULL;
+  self->sorted_surfaces.tail = NULL;
+  self->sorted_surfaces.length = 0;
+}
+
+const GList *
+_gdk_macos_display_get_surfaces (GdkMacosDisplay *self)
+{
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), NULL);
+
+  if (self->sorted_surfaces.length == 0)
+    {
+      GDK_BEGIN_MACOS_ALLOC_POOL;
+
+      NSArray *array = [NSApp orderedWindows];
+      GQueue sorted = G_QUEUE_INIT;
+
+      for (id obj in array)
+        {
+          NSWindow *nswindow = (NSWindow *)obj;
+          GdkMacosSurface *surface;
+
+          if (!GDK_IS_MACOS_WINDOW (nswindow))
+            continue;
+
+          surface = [(GdkMacosWindow *)nswindow gdkSurface];
+
+          surface->sorted.prev = NULL;
+          surface->sorted.next = NULL;
+
+          g_queue_push_tail_link (&sorted, &surface->sorted);
+        }
+
+      self->sorted_surfaces = sorted;
+
+      /* We don't get notification of clipboard changes from the system so we
+       * instead update it every time the foreground changes (and thusly
+       * rebuild the sorted list).  Things could change other ways, such as
+       * with scripts, but that is currently out of scope for us.
+       */
+      _gdk_macos_clipboard_check_externally_modified (
+        GDK_MACOS_CLIPBOARD (GDK_DISPLAY (self)->clipboard));
+
+      GDK_END_MACOS_ALLOC_POOL;
+    }
+
+  return self->sorted_surfaces.head;
+}
+
+void
+_gdk_macos_display_warp_pointer (GdkMacosDisplay *self,
+                                 int              x,
+                                 int              y)
+{
+  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+
+  _gdk_macos_display_to_display_coords (self, x, y, &x, &y);
+
+  CGWarpMouseCursorPosition ((CGPoint) { x, y });
+}
diff --git a/gdk/macos/gdkmacosdisplay.h b/gdk/macos/gdkmacosdisplay.h
new file mode 100644 (file)
index 0000000..7c5730d
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_DISPLAY_H__
+#define __GDK_MACOS_DISPLAY_H__
+
+#if !defined (__GDKMACOS_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gdk/macos/gdkmacos.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+#ifdef GTK_COMPILATION
+typedef struct _GdkMacosDisplay GdkMacosDisplay;
+#else
+typedef GdkDisplay GdkMacosDisplay;
+#endif
+typedef struct _GdkMacosDisplayClass GdkMacosDisplayClass;
+
+#define GDK_TYPE_MACOS_DISPLAY       (gdk_macos_display_get_type())
+#define GDK_MACOS_DISPLAY(object)    (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_DISPLAY, GdkMacosDisplay))
+#define GDK_IS_MACOS_DISPLAY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_DISPLAY))
+
+GDK_AVAILABLE_IN_ALL
+GType gdk_macos_display_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_DISPLAY_H__ */
diff --git a/gdk/macos/gdkmacosdrag-private.h b/gdk/macos/gdkmacosdrag-private.h
new file mode 100644 (file)
index 0000000..98075f2
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_DRAG_PRIVATE_H__
+#define __GDK_MACOS_DRAG_PRIVATE_H__
+
+#include "gdkdragprivate.h"
+
+#include "gdkmacosdragsurface-private.h"
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_MACOS_DRAG            (gdk_macos_drag_get_type ())
+#define GDK_MACOS_DRAG(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_DRAG, GdkMacosDrag))
+#define GDK_MACOS_DRAG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_MACOS_DRAG, GdkMacosDragClass))
+#define GDK_IS_MACOS_DRAG(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_DRAG))
+#define GDK_IS_MACOS_DRAG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_MACOS_DRAG))
+#define GDK_MACOS_DRAG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_MACOS_DRAG, GdkMacosDragClass))
+
+typedef struct _GdkMacosDrag GdkMacosDrag;
+typedef struct _GdkMacosDragClass GdkMacosDragClass;
+
+struct _GdkMacosDrag
+{
+  GdkDrag parent_instance;
+
+  GdkMacosDragSurface *drag_surface;
+  GdkSeat *drag_seat;
+  GdkCursor *cursor;
+
+  int hot_x;
+  int hot_y;
+
+  int last_x;
+  int last_y;
+
+  int start_x;
+  int start_y;
+
+  guint did_update : 1;
+  guint cancelled : 1;
+};
+
+struct _GdkMacosDragClass
+{
+  GdkDragClass parent_class;
+};
+
+GType    gdk_macos_drag_get_type (void) G_GNUC_CONST;
+gboolean _gdk_macos_drag_begin   (GdkMacosDrag *self);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_DRAG_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacosdrag.c b/gdk/macos/gdkmacosdrag.c
new file mode 100644 (file)
index 0000000..de1324c
--- /dev/null
@@ -0,0 +1,617 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "gdkdeviceprivate.h"
+#include "gdkintl.h"
+
+#include "gdkmacoscursor-private.h"
+#include "gdkmacosdisplay-private.h"
+#include "gdkmacosdrag-private.h"
+#include "gdkmacosdragsurface-private.h"
+
+#define BIG_STEP 20
+#define SMALL_STEP 1
+#define ANIM_TIME 500000 /* .5 seconds */
+
+typedef struct
+{
+  GdkMacosDrag  *drag;
+  GdkFrameClock *frame_clock;
+  gint64         start_time;
+} GdkMacosZoomback;
+
+G_DEFINE_TYPE (GdkMacosDrag, gdk_macos_drag, GDK_TYPE_DRAG)
+
+enum {
+  PROP_0,
+  PROP_DRAG_SURFACE,
+  N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static double
+ease_out_cubic (double t)
+{
+  double p = t - 1;
+  return p * p * p + 1;
+}
+
+static void
+gdk_macos_zoomback_destroy (GdkMacosZoomback *zb)
+{
+  gdk_surface_hide (GDK_SURFACE (zb->drag->drag_surface));
+  g_clear_object (&zb->drag);
+  g_slice_free (GdkMacosZoomback, zb);
+}
+
+static gboolean
+gdk_macos_zoomback_timeout (gpointer data)
+{
+  GdkMacosZoomback *zb = data;
+  GdkFrameClock *frame_clock;
+  GdkMacosDrag *drag;
+  gint64 current_time;
+  double f;
+  double t;
+
+  g_assert (zb != NULL);
+  g_assert (GDK_IS_MACOS_DRAG (zb->drag));
+
+  drag = zb->drag;
+  frame_clock = zb->frame_clock;
+
+  if (!frame_clock)
+    return G_SOURCE_REMOVE;
+
+  current_time = gdk_frame_clock_get_frame_time (frame_clock);
+  f = (current_time - zb->start_time) / (double) ANIM_TIME;
+  if (f >= 1.0)
+    return G_SOURCE_REMOVE;
+
+  t = ease_out_cubic (f);
+
+  _gdk_macos_surface_move (GDK_MACOS_SURFACE (drag->drag_surface),
+                           (drag->last_x - drag->hot_x) +
+                           (drag->start_x - drag->last_x) * t,
+                           (drag->last_y - drag->hot_y) +
+                           (drag->start_y - drag->last_y) * t);
+  _gdk_macos_surface_set_opacity (GDK_MACOS_SURFACE (drag->drag_surface), 1.0 - f);
+
+  /* Make sure we're topmost */
+  _gdk_macos_surface_show (GDK_MACOS_SURFACE (drag->drag_surface));
+
+  return G_SOURCE_CONTINUE;
+}
+
+static GdkSurface *
+gdk_macos_drag_get_drag_surface (GdkDrag *drag)
+{
+  return GDK_SURFACE (GDK_MACOS_DRAG (drag)->drag_surface);
+}
+
+static void
+gdk_macos_drag_set_hotspot (GdkDrag *drag,
+                            int      hot_x,
+                            int      hot_y)
+{
+  GdkMacosDrag *self = (GdkMacosDrag *)drag;
+  int change_x;
+  int change_y;
+
+  g_assert (GDK_IS_MACOS_DRAG (self));
+
+  change_x = hot_x - self->hot_x;
+  change_y = hot_y - self->hot_y;
+
+  self->hot_x = hot_x;
+  self->hot_y = hot_y;
+
+  if (change_x || change_y)
+    _gdk_macos_surface_move (GDK_MACOS_SURFACE (self->drag_surface),
+                             GDK_SURFACE (self->drag_surface)->x + change_x,
+                             GDK_SURFACE (self->drag_surface)->y + change_y);
+}
+
+static void
+gdk_macos_drag_drop_done (GdkDrag  *drag,
+                          gboolean  success)
+{
+  GdkMacosDrag *self = (GdkMacosDrag *)drag;
+  GdkMacosZoomback *zb;
+  guint id;
+
+  g_assert (GDK_IS_MACOS_DRAG (self));
+
+  if (success)
+    {
+      gdk_surface_hide (GDK_SURFACE (self->drag_surface));
+      g_object_unref (drag);
+      return;
+    }
+
+  /* Apple HIG suggests doing a "zoomback" animation of the surface back
+   * towards the original position.
+   */
+  zb = g_slice_new0 (GdkMacosZoomback);
+  zb->drag = g_object_ref (self);
+  zb->frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self->drag_surface));
+  zb->start_time = gdk_frame_clock_get_frame_time (zb->frame_clock);
+
+  id = g_timeout_add_full (G_PRIORITY_DEFAULT, 17,
+                           gdk_macos_zoomback_timeout,
+                           zb,
+                           (GDestroyNotify) gdk_macos_zoomback_destroy);
+  g_source_set_name_by_id (id, "[gtk] gdk_macos_zoomback_timeout");
+  g_object_unref (drag);
+}
+
+static void
+gdk_macos_drag_set_cursor (GdkDrag   *drag,
+                           GdkCursor *cursor)
+{
+  GdkMacosDrag *self = (GdkMacosDrag *)drag;
+  NSCursor *nscursor;
+
+  g_assert (GDK_IS_MACOS_DRAG (self));
+  g_assert (!cursor || GDK_IS_CURSOR (cursor));
+
+  g_set_object (&self->cursor, cursor);
+
+  nscursor = _gdk_macos_cursor_get_ns_cursor (cursor);
+
+  if (nscursor != NULL)
+    [nscursor set];
+}
+
+static gboolean
+drag_grab (GdkMacosDrag *self)
+{
+  GdkSeat *seat;
+
+  g_assert (GDK_IS_MACOS_DRAG (self));
+
+  seat = gdk_device_get_seat (gdk_drag_get_device (GDK_DRAG (self)));
+
+  if (gdk_seat_grab (seat,
+                     GDK_SURFACE (self->drag_surface),
+                     GDK_SEAT_CAPABILITY_ALL_POINTING,
+                     FALSE,
+                     self->cursor,
+                     NULL,
+                     NULL,
+                     NULL) != GDK_GRAB_SUCCESS)
+    return FALSE;
+
+  g_set_object (&self->drag_seat, seat);
+
+  return TRUE;
+}
+
+static void
+drag_ungrab (GdkMacosDrag *self)
+{
+  GdkDisplay *display;
+
+  g_assert (GDK_IS_MACOS_DRAG (self));
+
+  display = gdk_drag_get_display (GDK_DRAG (self));
+  _gdk_macos_display_break_all_grabs (GDK_MACOS_DISPLAY (display), GDK_CURRENT_TIME);
+}
+
+static void
+gdk_macos_drag_cancel (GdkDrag             *drag,
+                       GdkDragCancelReason  reason)
+{
+  GdkMacosDrag *self = (GdkMacosDrag *)drag;
+
+  g_assert (GDK_IS_MACOS_DRAG (self));
+
+  if (self->cancelled)
+    return;
+
+  self->cancelled = TRUE;
+  drag_ungrab (self);
+  gdk_drag_drop_done (drag, FALSE);
+}
+
+static void
+gdk_macos_drag_drop_performed (GdkDrag *drag,
+                               guint32  time)
+{
+  GdkMacosDrag *self = (GdkMacosDrag *)drag;
+
+  g_assert (GDK_IS_MACOS_DRAG (self));
+
+  drag_ungrab (self);
+  g_signal_emit_by_name (drag, "dnd-finished");
+  gdk_drag_drop_done (drag, TRUE);
+}
+
+static void
+gdk_drag_get_current_actions (GdkModifierType  state,
+                              gint             button,
+                              GdkDragAction    actions,
+                              GdkDragAction   *suggested_action,
+                              GdkDragAction   *possible_actions)
+{
+  *suggested_action = 0;
+  *possible_actions = 0;
+
+  if ((button == GDK_BUTTON_MIDDLE || button == GDK_BUTTON_SECONDARY) && (actions & GDK_ACTION_ASK))
+    {
+      *suggested_action = GDK_ACTION_ASK;
+      *possible_actions = actions;
+    }
+  else if (state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK))
+    {
+      if ((state & GDK_SHIFT_MASK) && (state & GDK_CONTROL_MASK))
+        {
+          if (actions & GDK_ACTION_LINK)
+            {
+              *suggested_action = GDK_ACTION_LINK;
+              *possible_actions = GDK_ACTION_LINK;
+            }
+        }
+      else if (state & GDK_CONTROL_MASK)
+        {
+          if (actions & GDK_ACTION_COPY)
+            {
+              *suggested_action = GDK_ACTION_COPY;
+              *possible_actions = GDK_ACTION_COPY;
+            }
+        }
+      else
+        {
+          if (actions & GDK_ACTION_MOVE)
+            {
+              *suggested_action = GDK_ACTION_MOVE;
+              *possible_actions = GDK_ACTION_MOVE;
+            }
+        }
+    }
+  else
+    {
+      *possible_actions = actions;
+
+      if ((state & (GDK_ALT_MASK)) && (actions & GDK_ACTION_ASK))
+        *suggested_action = GDK_ACTION_ASK;
+      else if (actions & GDK_ACTION_COPY)
+        *suggested_action =  GDK_ACTION_COPY;
+      else if (actions & GDK_ACTION_MOVE)
+        *suggested_action = GDK_ACTION_MOVE;
+      else if (actions & GDK_ACTION_LINK)
+        *suggested_action = GDK_ACTION_LINK;
+    }
+}
+
+static void
+gdk_drag_update (GdkDrag         *drag,
+                 gdouble          x_root,
+                 gdouble          y_root,
+                 GdkModifierType  mods,
+                 guint32          evtime)
+{
+  GdkMacosDrag *self = (GdkMacosDrag *)drag;
+  GdkDragAction suggested_action;
+  GdkDragAction possible_actions;
+
+  g_assert (GDK_IS_MACOS_DRAG (self));
+
+  self->last_x = x_root;
+  self->last_y = y_root;
+
+  gdk_drag_get_current_actions (mods,
+                                GDK_BUTTON_PRIMARY,
+                                gdk_drag_get_actions (drag),
+                                &suggested_action,
+                                &possible_actions);
+
+  _gdk_macos_drag_surface_drag_motion (self->drag_surface,
+                                       x_root - self->hot_x,
+                                       y_root - self->hot_y,
+                                       suggested_action,
+                                       possible_actions,
+                                       evtime);
+
+  if (!self->did_update)
+    {
+      self->start_x = self->last_x;
+      self->start_y = self->last_y;
+      self->did_update = TRUE;
+    }
+}
+
+static gboolean
+gdk_dnd_handle_motion_event (GdkDrag  *drag,
+                             GdkEvent *event)
+{
+  double x, y;
+  int x_root, y_root;
+
+  g_assert (GDK_IS_MACOS_DRAG (drag));
+  g_assert (event != NULL);
+
+  /* Ignore motion while doing zoomback */
+  if (GDK_MACOS_DRAG (drag)->cancelled)
+    return FALSE;
+
+  gdk_event_get_position (event, &x, &y);
+  x_root = event->surface->x + x;
+  y_root = event->surface->y + y;
+  gdk_drag_update (drag, x_root, y_root,
+                   gdk_event_get_modifier_state (event),
+                   gdk_event_get_time (event));
+
+  return TRUE;
+}
+
+static gboolean
+gdk_dnd_handle_grab_broken_event (GdkDrag  *drag,
+                                  GdkEvent *event)
+{
+  GdkMacosDrag *self = GDK_MACOS_DRAG (drag);
+  gboolean is_implicit = gdk_grab_broken_event_get_implicit (event);
+  GdkSurface *grab_surface = gdk_grab_broken_event_get_grab_surface (event);
+
+  /* Don't cancel if we break the implicit grab from the initial button_press. */
+  if (is_implicit || grab_surface == (GdkSurface *)self->drag_surface)
+    return FALSE;
+
+  if (gdk_event_get_device (event) != gdk_drag_get_device (drag))
+    return FALSE;
+
+  gdk_drag_cancel (drag, GDK_DRAG_CANCEL_ERROR);
+
+  return TRUE;
+}
+
+static gboolean
+gdk_dnd_handle_button_event (GdkDrag  *drag,
+                             GdkEvent *event)
+{
+  GdkMacosDrag *self = GDK_MACOS_DRAG (drag);
+
+  g_assert (GDK_IS_MACOS_DRAG (self));
+  g_assert (event != NULL);
+
+#if 0
+  /* FIXME: Check the button matches */
+  if (event->button != self->button)
+    return FALSE;
+#endif
+
+  if (gdk_drag_get_selected_action (drag) != 0)
+    g_signal_emit_by_name (drag, "drop-performed");
+  else
+    gdk_drag_cancel (drag, GDK_DRAG_CANCEL_NO_TARGET);
+
+  return TRUE;
+}
+
+static gboolean
+gdk_dnd_handle_key_event (GdkDrag  *drag,
+                          GdkEvent *event)
+{
+  GdkMacosDrag *self = GDK_MACOS_DRAG (drag);
+  GdkModifierType state;
+  GdkDevice *pointer;
+  gint dx, dy;
+
+  dx = dy = 0;
+  state = gdk_event_get_modifier_state (event);
+  pointer = gdk_device_get_associated_device (gdk_event_get_device (event));
+
+  if (event->event_type == GDK_KEY_PRESS)
+    {
+      guint keyval = gdk_key_event_get_keyval (event);
+
+      switch (keyval)
+        {
+        case GDK_KEY_Escape:
+          gdk_drag_cancel (drag, GDK_DRAG_CANCEL_USER_CANCELLED);
+          return TRUE;
+
+        case GDK_KEY_space:
+        case GDK_KEY_Return:
+        case GDK_KEY_ISO_Enter:
+        case GDK_KEY_KP_Enter:
+        case GDK_KEY_KP_Space:
+          if (gdk_drag_get_selected_action (drag) != 0)
+            g_signal_emit_by_name (drag, "drop-performed");
+          else
+            gdk_drag_cancel (drag, GDK_DRAG_CANCEL_NO_TARGET);
+
+          return TRUE;
+
+        case GDK_KEY_Up:
+        case GDK_KEY_KP_Up:
+          dy = (state & GDK_ALT_MASK) ? -BIG_STEP : -SMALL_STEP;
+          break;
+
+        case GDK_KEY_Down:
+        case GDK_KEY_KP_Down:
+          dy = (state & GDK_ALT_MASK) ? BIG_STEP : SMALL_STEP;
+          break;
+
+        case GDK_KEY_Left:
+        case GDK_KEY_KP_Left:
+          dx = (state & GDK_ALT_MASK) ? -BIG_STEP : -SMALL_STEP;
+          break;
+
+        case GDK_KEY_Right:
+        case GDK_KEY_KP_Right:
+          dx = (state & GDK_ALT_MASK) ? BIG_STEP : SMALL_STEP;
+          break;
+
+        default:
+          break;
+        }
+    }
+
+  /* The state is not yet updated in the event, so we need
+   * to query it here. We could use XGetModifierMapping, but
+   * that would be overkill.
+   */
+  _gdk_device_query_state (pointer, NULL, NULL, NULL, NULL, &state);
+
+  if (dx != 0 || dy != 0)
+    {
+      GdkDisplay *display = gdk_event_get_display ((GdkEvent *)event);
+
+      self->last_x += dx;
+      self->last_y += dy;
+
+      _gdk_macos_display_warp_pointer (GDK_MACOS_DISPLAY (display),
+                                       self->last_x,
+                                       self->last_y);
+    }
+
+  gdk_drag_update (drag,
+                   self->last_x, self->last_y,
+                   state,
+                   gdk_event_get_time (event));
+
+  return TRUE;
+}
+
+static gboolean
+gdk_macos_drag_handle_event (GdkDrag  *drag,
+                             GdkEvent *event)
+{
+  g_assert (GDK_IS_MACOS_DRAG (drag));
+  g_assert (event != NULL);
+
+  switch ((guint) event->event_type)
+    {
+    case GDK_MOTION_NOTIFY:
+      return gdk_dnd_handle_motion_event (drag, event);
+
+    case GDK_BUTTON_RELEASE:
+      return gdk_dnd_handle_button_event (drag, event);
+
+    case GDK_KEY_PRESS:
+    case GDK_KEY_RELEASE:
+      return gdk_dnd_handle_key_event (drag, event);
+
+    case GDK_GRAB_BROKEN:
+      return gdk_dnd_handle_grab_broken_event (drag, event);
+
+    default:
+      return FALSE;
+    }
+}
+
+static void
+gdk_macos_drag_finalize (GObject *object)
+{
+  GdkMacosDrag *self = (GdkMacosDrag *)object;
+  GdkMacosDragSurface *drag_surface = g_steal_pointer (&self->drag_surface);
+
+  g_clear_object (&self->cursor);
+  g_clear_object (&self->drag_seat);
+
+  G_OBJECT_CLASS (gdk_macos_drag_parent_class)->finalize (object);
+
+  if (drag_surface)
+    gdk_surface_destroy (GDK_SURFACE (drag_surface));
+}
+
+static void
+gdk_macos_drag_get_property (GObject    *object,
+                             guint       prop_id,
+                             GValue     *value,
+                             GParamSpec *pspec)
+{
+  GdkMacosDrag *self = GDK_MACOS_DRAG (object);
+
+  switch (prop_id)
+    {
+    case PROP_DRAG_SURFACE:
+      g_value_set_object (value, self->drag_surface);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gdk_macos_drag_set_property (GObject      *object,
+                             guint         prop_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+  GdkMacosDrag *self = GDK_MACOS_DRAG (object);
+
+  switch (prop_id)
+    {
+    case PROP_DRAG_SURFACE:
+      self->drag_surface = g_value_dup_object (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gdk_macos_drag_class_init (GdkMacosDragClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkDragClass *drag_class = GDK_DRAG_CLASS (klass);
+
+  object_class->finalize = gdk_macos_drag_finalize;
+  object_class->get_property = gdk_macos_drag_get_property;
+  object_class->set_property = gdk_macos_drag_set_property;
+
+  drag_class->get_drag_surface = gdk_macos_drag_get_drag_surface;
+  drag_class->set_hotspot = gdk_macos_drag_set_hotspot;
+  drag_class->drop_done = gdk_macos_drag_drop_done;
+  drag_class->set_cursor = gdk_macos_drag_set_cursor;
+  drag_class->cancel = gdk_macos_drag_cancel;
+  drag_class->drop_performed = gdk_macos_drag_drop_performed;
+  drag_class->handle_event = gdk_macos_drag_handle_event;
+
+  properties [PROP_DRAG_SURFACE] =
+    g_param_spec_object ("drag-surface",
+                         P_("Drag Surface"),
+                         P_("Drag Surface"),
+                         GDK_TYPE_MACOS_DRAG_SURFACE,
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+gdk_macos_drag_init (GdkMacosDrag *self)
+{
+}
+
+gboolean
+_gdk_macos_drag_begin (GdkMacosDrag *self)
+{
+  g_return_val_if_fail (GDK_IS_MACOS_DRAG (self), FALSE);
+
+  _gdk_macos_surface_show (GDK_MACOS_SURFACE (self->drag_surface));
+
+  return drag_grab (self);
+}
diff --git a/gdk/macos/gdkmacosdragsurface-private.h b/gdk/macos/gdkmacosdragsurface-private.h
new file mode 100644 (file)
index 0000000..cf7408f
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_DRAG_SURFACE_PRIVATE_H__
+#define __GDK_MACOS_DRAG_SURFACE_PRIVATE_H__
+
+#include "gdkmacossurface-private.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GdkMacosDragSurface      GdkMacosDragSurface;
+typedef struct _GdkMacosDragSurfaceClass GdkMacosDragSurfaceClass;
+
+#define GDK_TYPE_MACOS_DRAG_SURFACE       (_gdk_macos_drag_surface_get_type())
+#define GDK_MACOS_DRAG_SURFACE(object)    (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_DRAG_SURFACE, GdkMacosDragSurface))
+#define GDK_IS_MACOS_DRAG_SURFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_DRAG_SURFACE))
+
+GType            _gdk_macos_drag_surface_get_type    (void);
+GdkMacosSurface *_gdk_macos_drag_surface_new         (GdkMacosDisplay *display,
+                                                      GdkFrameClock   *frame_clock,
+                                                      int              x,
+                                                      int              y,
+                                                      int              width,
+                                                      int              height);
+void             _gdk_macos_drag_surface_drag_motion (GdkMacosDragSurface *self,
+                                                      int                  x_root,
+                                                      int                  y_root,
+                                                      GdkDragAction        suggested_action,
+                                                      GdkDragAction        possible_actions,
+                                                      guint32              evtime);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_DRAG_SURFACE_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacosdragsurface.c b/gdk/macos/gdkmacosdragsurface.c
new file mode 100644 (file)
index 0000000..2b03583
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "gdkdragsurfaceprivate.h"
+
+#include "gdkmacosdragsurface-private.h"
+#include "gdkmacosdisplay-private.h"
+#include "gdkmacosutils-private.h"
+
+struct _GdkMacosDragSurface
+{
+  GdkMacosSurface parent_instance;
+};
+
+struct _GdkMacosDragSurfaceClass
+{
+  GdkMacosSurfaceClass parent_instance;
+};
+
+static gboolean
+_gdk_macos_drag_surface_present (GdkDragSurface *surface,
+                                 int             width,
+                                 int             height)
+{
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+
+  _gdk_macos_surface_move_resize (GDK_MACOS_SURFACE (surface),
+                                  -1, -1,
+                                  width, height);
+
+  if (!GDK_SURFACE_IS_MAPPED (GDK_SURFACE (surface)))
+    _gdk_macos_surface_show (GDK_MACOS_SURFACE (surface));
+
+  return GDK_SURFACE_IS_MAPPED (GDK_SURFACE (surface));
+}
+
+static void
+drag_surface_iface_init (GdkDragSurfaceInterface *iface)
+{
+  iface->present = _gdk_macos_drag_surface_present;
+}
+
+G_DEFINE_TYPE_WITH_CODE (GdkMacosDragSurface, _gdk_macos_drag_surface, GDK_TYPE_MACOS_SURFACE,
+                         G_IMPLEMENT_INTERFACE (GDK_TYPE_DRAG_SURFACE, drag_surface_iface_init))
+
+static void
+_gdk_macos_drag_surface_class_init (GdkMacosDragSurfaceClass *klass)
+{
+}
+
+static void
+_gdk_macos_drag_surface_init (GdkMacosDragSurface *self)
+{
+}
+
+GdkMacosSurface *
+_gdk_macos_drag_surface_new (GdkMacosDisplay *display,
+                             GdkFrameClock   *frame_clock,
+                             int              x,
+                             int              y,
+                             int              width,
+                             int              height)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  GdkMacosWindow *window;
+  GdkMacosSurface *self;
+  NSScreen *screen;
+  NSUInteger style_mask;
+  NSRect content_rect;
+  NSRect screen_rect;
+  int nx;
+  int ny;
+
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
+  g_return_val_if_fail (!frame_clock || GDK_IS_FRAME_CLOCK (frame_clock), NULL);
+
+  style_mask = NSWindowStyleMaskBorderless;
+
+  _gdk_macos_display_to_display_coords (display, x, y, &nx, &ny);
+
+  screen = _gdk_macos_display_get_screen_at_display_coords (display, nx, ny);
+  screen_rect = [screen frame];
+  nx -= screen_rect.origin.x;
+  ny -= screen_rect.origin.y;
+  content_rect = NSMakeRect (nx, ny - height, width, height);
+
+  window = [[GdkMacosWindow alloc] initWithContentRect:content_rect
+                                             styleMask:style_mask
+                                               backing:NSBackingStoreBuffered
+                                                 defer:NO
+                                                screen:screen];
+
+  [window setOpaque:NO];
+  [window setBackgroundColor:[NSColor clearColor]];
+  [window setDecorated:NO];
+
+  self = g_object_new (GDK_TYPE_MACOS_DRAG_SURFACE,
+                       "display", display,
+                       "frame-clock", frame_clock,
+                       "native", window,
+                       NULL);
+
+  GDK_END_MACOS_ALLOC_POOL;
+
+  return g_steal_pointer (&self);
+}
+
+void
+_gdk_macos_drag_surface_drag_motion (GdkMacosDragSurface *self,
+                                     int                  x_root,
+                                     int                  y_root,
+                                     GdkDragAction        suggested_action,
+                                     GdkDragAction        possible_actions,
+                                     guint32              evtime)
+{
+  g_return_if_fail (GDK_IS_MACOS_DRAG_SURFACE (self));
+
+  _gdk_macos_surface_move (GDK_MACOS_SURFACE (self), x_root, y_root);
+}
diff --git a/gdk/macos/gdkmacoseventsource-private.h b/gdk/macos/gdkmacoseventsource-private.h
new file mode 100644 (file)
index 0000000..09853a1
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_EVENT_SOURCE_PRIVATE_H__
+#define __GDK_MACOS_EVENT_SOURCE_PRIVATE_H__
+
+#include <AppKit/AppKit.h>
+
+#include "gdkmacosdisplay.h"
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+  GDK_MACOS_EVENT_SUBTYPE_EVENTLOOP,
+} GdkMacosEventSubType;
+
+GSource  *_gdk_macos_event_source_new           (GdkMacosDisplay *display);
+NSEvent  *_gdk_macos_event_source_get_pending   (void);
+gboolean  _gdk_macos_event_source_check_pending (void);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_EVENT_SOURCE_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacoseventsource.c b/gdk/macos/gdkmacoseventsource.c
new file mode 100644 (file)
index 0000000..f173433
--- /dev/null
@@ -0,0 +1,1094 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ * Copyright (C) 2005-2007 Imendio AB
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+#include "gdkdisplayprivate.h"
+#include "gdkinternals.h"
+
+#include "gdkmacoseventsource-private.h"
+#include "gdkmacosdisplay-private.h"
+
+/*
+ * This file implementations integration between the GLib main loop and
+ * the native system of the Core Foundation run loop and Cocoa event
+ * handling. There are basically two different cases that we need to
+ * handle: either the GLib main loop is in control (the application
+ * has called gtk_main(), or is otherwise iterating the main loop), or
+ * CFRunLoop is in control (we are in a modal operation such as window
+ * resizing or drag-and-drop.)
+ *
+ * When the GLib main loop is in control we integrate in native event
+ * handling in two ways: first we add a GSource that handles checking
+ * whether there are native events available, translating native events
+ * to GDK events, and dispatching GDK events. Second we replace the
+ * "poll function" of the GLib main loop with our own version that knows
+ * how to wait for both the file descriptors and timeouts that GLib is
+ * interested in and also for incoming native events.
+ *
+ * When CFRunLoop is in control, we integrate in GLib main loop handling
+ * by adding a "run loop observer" that gives us notification at various
+ * points in the run loop cycle. We map these points onto the corresponding
+ * stages of the GLib main loop (prepare, check, dispatch), and make the
+ * appropriate calls into GLib.
+ *
+ * Both cases share a single problem: the OS X API’s don’t allow us to
+ * wait simultaneously for file descriptors and for events. So when we
+ * need to do a blocking wait that includes file descriptor activity, we
+ * push the actual work of calling select() to a helper thread (the
+ * "select thread") and wait for native events in the main thread.
+ *
+ * The main known limitation of this code is that if a callback is triggered
+ * via the OS X run loop while we are "polling" (in either case described
+ * above), iteration of the GLib main loop is not possible from within
+ * that callback. If the programmer tries to do so explicitly, then they
+ * will get a warning from GLib "main loop already active in another thread".
+ */
+
+/******* State for run loop iteration *******/
+
+/* Count of number of times we've gotten an "Entry" notification for
+ * our run loop observer.
+ */
+static int current_loop_level = 0;
+
+/* Run loop level at which we acquired ownership of the GLib main
+ * loop. See note in run_loop_entry(). -1 means that we don’t have
+ * ownership
+ */
+static int acquired_loop_level = -1;
+
+/* Between run_loop_before_waiting() and run_loop_after_waiting();
+ * whether we we need to call select_thread_collect_poll()
+ */
+static gboolean run_loop_polling_async = FALSE;
+
+/* Between run_loop_before_waiting() and run_loop_after_waiting();
+ * max_prioritiy to pass to g_main_loop_check()
+ */
+static gint run_loop_max_priority;
+
+/* Timer that we've added to wake up the run loop when a GLib timeout
+ */
+static CFRunLoopTimerRef run_loop_timer = NULL;
+
+/* These are the file descriptors that are we are polling out of
+ * the run loop. (We keep the array around and reuse it to avoid
+ * constant allocations.)
+ */
+#define RUN_LOOP_POLLFDS_INITIAL_SIZE 16
+static GPollFD *run_loop_pollfds;
+static guint run_loop_pollfds_size; /* Allocated size of the array */
+static guint run_loop_n_pollfds;    /* Number of file descriptors in the array */
+
+/******* Other global variables *******/
+
+/* Since we count on replacing the GLib main loop poll function as our
+ * method of integrating Cocoa event handling into the GLib main loop
+ * we need to make sure that the poll function is always called even
+ * when there are no file descriptors that need to be polled. To do
+ * this, we add a dummy GPollFD to our event source with a file
+ * descriptor of “-1”. Then any time that GLib is polling the event
+ * source, it will call our poll function.
+ */
+static GPollFD event_poll_fd;
+
+/* Current NSEvents that we've gotten from Cocoa but haven't yet converted
+ * to GdkEvents. We wait until our dispatch() function to do the conversion
+ * since the conversion can conceivably cause signals to be emmitted
+ * or other things that shouldn’t happen inside a poll function.
+ */
+static GQueue *current_events;
+
+/* The default poll function for GLib; we replace this with our own
+ * Cocoa-aware version and then call the old version to do actual
+ * file descriptor polling. There’s no actual need to chain to the
+ * old one; we could reimplement the same functionality from scratch,
+ * but since the default implementation does the right thing, why
+ * bother.
+ */
+static GPollFunc old_poll_func;
+
+/* Reference to the run loop of the main thread. (There is a unique
+ * CFRunLoop per thread.)
+ */
+static CFRunLoopRef main_thread_run_loop;
+
+/* Normally the Cocoa main loop maintains an NSAutoReleasePool and frees
+ * it on every iteration. Since we are replacing the main loop we have
+ * to provide this functionality ourself. We free and replace the
+ * auto-release pool in our sources prepare() function.
+ */
+static NSAutoreleasePool *autorelease_pool;
+
+/* Flag when we've called nextEventMatchingMask ourself; this triggers
+ * a run loop iteration, so we need to detect that and avoid triggering
+ * our "run the GLib main looop while the run loop is active machinery.
+ */
+static gint getting_events = 0;
+
+/************************************************************
+ *********              Select Thread               *********
+ ************************************************************/
+
+/* The states in our state machine, see comments in select_thread_func()
+ * for descriptiions of each state
+ */
+typedef enum {
+  BEFORE_START,
+  WAITING,
+  POLLING_QUEUED,
+  POLLING_RESTART,
+  POLLING_DESCRIPTORS,
+} SelectThreadState;
+
+#ifdef G_ENABLE_DEBUG
+static const char *const state_names[]  = {
+  "BEFORE_START",
+  "WAITING",
+  "POLLING_QUEUED",
+  "POLLING_RESTART",
+  "POLLING_DESCRIPTORS"
+};
+#endif
+
+static SelectThreadState select_thread_state = BEFORE_START;
+
+static pthread_t select_thread;
+static pthread_mutex_t select_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t select_thread_cond = PTHREAD_COND_INITIALIZER;
+
+#define SELECT_THREAD_LOCK() pthread_mutex_lock (&select_thread_mutex)
+#define SELECT_THREAD_UNLOCK() pthread_mutex_unlock (&select_thread_mutex)
+#define SELECT_THREAD_SIGNAL() pthread_cond_signal (&select_thread_cond)
+#define SELECT_THREAD_WAIT() pthread_cond_wait (&select_thread_cond, &select_thread_mutex)
+
+/* These are the file descriptors that the select thread is currently
+ * polling.
+ */
+static GPollFD *current_pollfds;
+static guint current_n_pollfds;
+
+/* These are the file descriptors that the select thread should pick
+ * up and start polling when it has a chance.
+ */
+static GPollFD *next_pollfds;
+static guint next_n_pollfds;
+
+/* Pipe used to wake up the select thread */
+static gint select_thread_wakeup_pipe[2];
+
+/* Run loop source used to wake up the main thread */
+static CFRunLoopSourceRef select_main_thread_source;
+
+static void
+select_thread_set_state (SelectThreadState new_state)
+{
+  gboolean old_state;
+
+  if (select_thread_state == new_state)
+    return;
+
+  GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Select thread state: %s => %s", state_names[select_thread_state], state_names[new_state]));
+
+  old_state = select_thread_state;
+  select_thread_state = new_state;
+  if (old_state == WAITING && new_state != WAITING)
+    SELECT_THREAD_SIGNAL ();
+}
+
+static void
+signal_main_thread (void)
+{
+  GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Waking up main thread"));
+
+  /* If we are in nextEventMatchingMask, then we need to make sure an
+   * event gets queued, otherwise it's enough to simply wake up the
+   * main thread run loop
+   */
+  if (!run_loop_polling_async)
+    CFRunLoopSourceSignal (select_main_thread_source);
+
+  /* Don't check for CFRunLoopIsWaiting() here because it causes a
+   * race condition (the loop could go into waiting state right after
+   * we checked).
+   */
+  CFRunLoopWakeUp (main_thread_run_loop);
+}
+
+static void *
+select_thread_func (void *arg)
+{
+  char c;
+
+  SELECT_THREAD_LOCK ();
+
+  while (TRUE)
+    {
+      switch (select_thread_state)
+        {
+        case BEFORE_START:
+          /* The select thread has not been started yet
+           */
+          g_assert_not_reached ();
+
+        case WAITING:
+          /* Waiting for a set of file descriptors to be submitted by the main thread
+           *
+           *  => POLLING_QUEUED: main thread thread submits a set of file descriptors
+           */
+          SELECT_THREAD_WAIT ();
+          break;
+
+        case POLLING_QUEUED:
+          /* Waiting for a set of file descriptors to be submitted by the main thread
+           *
+           *  => POLLING_DESCRIPTORS: select thread picks up the file descriptors to begin polling
+           */
+          g_free (current_pollfds);
+
+          current_pollfds = next_pollfds;
+          current_n_pollfds = next_n_pollfds;
+
+          next_pollfds = NULL;
+          next_n_pollfds = 0;
+
+          select_thread_set_state (POLLING_DESCRIPTORS);
+          break;
+
+        case POLLING_RESTART:
+          /* Select thread is currently polling a set of file descriptors, main thread has
+           * began a new iteration with the same set of file descriptors. We don't want to
+           * wake the select thread up and wait for it to restart immediately, but to avoid
+           * a race (described below in select_thread_start_polling()) we need to recheck after
+           * polling completes.
+           *
+           * => POLLING_DESCRIPTORS: select completes, main thread rechecks by polling again
+           * => POLLING_QUEUED: main thread submits a new set of file descriptors to be polled
+           */
+          select_thread_set_state (POLLING_DESCRIPTORS);
+          break;
+
+        case POLLING_DESCRIPTORS:
+          /* In the process of polling the file descriptors
+           *
+           *  => WAITING: polling completes when a file descriptor becomes active
+           *  => POLLING_QUEUED: main thread submits a new set of file descriptors to be polled
+           *  => POLLING_RESTART: main thread begins a new iteration with the same set file descriptors
+           */
+          SELECT_THREAD_UNLOCK ();
+          old_poll_func (current_pollfds, current_n_pollfds, -1);
+          SELECT_THREAD_LOCK ();
+
+          read (select_thread_wakeup_pipe[0], &c, 1);
+
+          if (select_thread_state == POLLING_DESCRIPTORS)
+            {
+              signal_main_thread ();
+              select_thread_set_state (WAITING);
+            }
+          break;
+        }
+    }
+}
+
+static void
+got_fd_activity (void *info)
+{
+  NSEvent *event;
+
+  /* Post a message so we'll break out of the message loop */
+  event = [NSEvent otherEventWithType: NSEventTypeApplicationDefined
+                             location: NSZeroPoint
+                        modifierFlags: 0
+                            timestamp: 0
+                         windowNumber: 0
+                              context: nil
+                              subtype: GDK_MACOS_EVENT_SUBTYPE_EVENTLOOP
+                                data1: 0
+                                data2: 0];
+
+  [NSApp postEvent:event atStart:YES];
+}
+
+static void
+select_thread_start (void)
+{
+  g_return_if_fail (select_thread_state == BEFORE_START);
+
+  pipe (select_thread_wakeup_pipe);
+  fcntl (select_thread_wakeup_pipe[0], F_SETFL, O_NONBLOCK);
+
+  CFRunLoopSourceContext source_context = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, got_fd_activity };
+  select_main_thread_source = CFRunLoopSourceCreate (NULL, 0, &source_context);
+
+  CFRunLoopAddSource (main_thread_run_loop, select_main_thread_source, kCFRunLoopCommonModes);
+
+  select_thread_state = WAITING;
+
+  while (TRUE)
+    {
+      if (pthread_create (&select_thread, NULL, select_thread_func, NULL) == 0)
+        break;
+
+      g_warning ("Failed to create select thread, sleeping and trying again");
+      sleep (1);
+    }
+}
+
+#ifdef G_ENABLE_DEBUG
+static void
+dump_poll_result (GPollFD *ufds,
+                  guint    nfds)
+{
+  GString *s;
+  gint i;
+
+  s = g_string_new ("");
+  for (i = 0; i < nfds; i++)
+    {
+      if (ufds[i].fd >= 0 && ufds[i].revents)
+        {
+          g_string_append_printf (s, " %d:", ufds[i].fd);
+          if (ufds[i].revents & G_IO_IN)
+            g_string_append (s, " in");
+          if (ufds[i].revents & G_IO_OUT)
+            g_string_append (s, " out");
+          if (ufds[i].revents & G_IO_PRI)
+            g_string_append (s, " pri");
+          g_string_append (s, "\n");
+        }
+    }
+  g_message ("%s", s->str);
+  g_string_free (s, TRUE);
+}
+#endif
+
+static gboolean
+pollfds_equal (GPollFD *old_pollfds,
+               guint    old_n_pollfds,
+               GPollFD *new_pollfds,
+               guint    new_n_pollfds)
+{
+  gint i;
+
+  if (old_n_pollfds != new_n_pollfds)
+    return FALSE;
+
+  for (i = 0; i < old_n_pollfds; i++)
+    {
+      if (old_pollfds[i].fd != new_pollfds[i].fd ||
+          old_pollfds[i].events != new_pollfds[i].events)
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
+/* Begins a polling operation with the specified GPollFD array; the
+ * timeout is used only to tell if the polling operation is blocking
+ * or non-blocking.
+ *
+ * Returns:
+ *  -1: No file descriptors ready, began asynchronous poll
+ *   0: No file descriptors ready, asynchronous poll not needed
+ * > 0: Number of file descriptors ready
+ */
+static gint
+select_thread_start_poll (GPollFD *ufds,
+                          guint    nfds,
+                          gint     timeout)
+{
+  gint n_ready;
+  gboolean have_new_pollfds = FALSE;
+  gint poll_fd_index = -1;
+  gint i;
+
+  for (i = 0; i < nfds; i++)
+    if (ufds[i].fd == -1)
+      {
+        poll_fd_index = i;
+        break;
+      }
+
+  if (nfds == 0 ||
+      (nfds == 1 && poll_fd_index >= 0))
+    {
+      GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Nothing to poll"));
+      return 0;
+    }
+
+  /* If we went immediately to an async poll, then we might decide to
+   * dispatch idle functions when higher priority file descriptor sources
+   * are ready to be dispatched. So we always need to first check
+   * check synchronously with a timeout of zero, and only when no
+   * sources are immediately ready, go to the asynchronous poll.
+   *
+   * Of course, if the timeout passed in is 0, then the synchronous
+   * check is sufficient and we never need to do the asynchronous poll.
+   */
+  n_ready = old_poll_func (ufds, nfds, 0);
+  if (n_ready > 0 || timeout == 0)
+    {
+#ifdef G_ENABLE_DEBUG
+      if ((_gdk_debug_flags & GDK_DEBUG_EVENTLOOP) && n_ready > 0)
+        {
+          g_message ("EventLoop: Found ready file descriptors before waiting");
+          dump_poll_result (ufds, nfds);
+        }
+#endif
+
+      return n_ready;
+    }
+
+  SELECT_THREAD_LOCK ();
+
+  if (select_thread_state == BEFORE_START)
+    {
+      select_thread_start ();
+    }
+
+  if (select_thread_state == POLLING_QUEUED)
+    {
+      /* If the select thread hasn't picked up the set of file descriptors yet
+       * then we can simply replace an old stale set with a new set.
+       */
+      if (!pollfds_equal (ufds, nfds, next_pollfds, next_n_pollfds - 1))
+        {
+          g_free (next_pollfds);
+          next_pollfds = NULL;
+          next_n_pollfds = 0;
+
+          have_new_pollfds = TRUE;
+        }
+    }
+  else if (select_thread_state == POLLING_RESTART || select_thread_state == POLLING_DESCRIPTORS)
+    {
+      /* If we are already in the process of polling the right set of file descriptors,
+       * there's no need for us to immediately force the select thread to stop polling
+       * and then restart again. And avoiding doing so increases the efficiency considerably
+       * in the common case where we have a set of basically inactive file descriptors that
+       * stay unchanged present as we process many events.
+       *
+       * However, we have to be careful that we don't hit the following race condition
+       *  Select Thread              Main Thread
+       *  -----------------          ---------------
+       *  Polling Completes
+       *                             Reads data or otherwise changes file descriptor state
+       *                             Checks if polling is current
+       *                             Does nothing (*)
+       *                             Releases lock
+       *  Acquires lock
+       *  Marks polling as complete
+       *  Wakes main thread
+       *                             Receives old stale file descriptor state
+       *
+       * To avoid this, when the new set of poll descriptors is the same as the current
+       * one, we transition to the POLLING_RESTART stage at the point marked (*). When
+       * the select thread wakes up from the poll because a file descriptor is active, if
+       * the state is POLLING_RESTART it immediately begins polling same the file descriptor
+       * set again. This normally will just return the same set of active file descriptors
+       * as the first time, but in sequence described above will properly update the
+       * file descriptor state.
+       *
+       * Special case: this RESTART logic is not needed if the only FD is the internal GLib
+       * "wakeup pipe" that is presented when threads are initialized.
+       *
+       * P.S.: The harm in the above sequence is mostly that sources can be signalled
+       *   as ready when they are no longer ready. This may prompt a blocking read
+       *   from a file descriptor that hangs.
+       */
+      if (!pollfds_equal (ufds, nfds, current_pollfds, current_n_pollfds - 1))
+        have_new_pollfds = TRUE;
+      else
+        {
+          if (!((nfds == 1 && poll_fd_index < 0 && g_thread_supported ()) ||
+                (nfds == 2 && poll_fd_index >= 0 && g_thread_supported ())))
+            select_thread_set_state (POLLING_RESTART);
+        }
+    }
+  else
+    have_new_pollfds = TRUE;
+
+  if (have_new_pollfds)
+    {
+      GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Submitting a new set of file descriptor to the select thread"));
+
+      g_assert (next_pollfds == NULL);
+
+      next_n_pollfds = nfds + 1;
+      next_pollfds = g_new (GPollFD, nfds + 1);
+      memcpy (next_pollfds, ufds, nfds * sizeof (GPollFD));
+
+      next_pollfds[nfds].fd = select_thread_wakeup_pipe[0];
+      next_pollfds[nfds].events = G_IO_IN;
+
+      if (select_thread_state != POLLING_QUEUED && select_thread_state != WAITING)
+        {
+          if (select_thread_wakeup_pipe[1])
+            {
+              char c = 'A';
+              write (select_thread_wakeup_pipe[1], &c, 1);
+            }
+        }
+
+      select_thread_set_state (POLLING_QUEUED);
+    }
+
+  SELECT_THREAD_UNLOCK ();
+
+  return -1;
+}
+
+/* End an asynchronous polling operation started with
+ * select_thread_collect_poll(). This must be called if and only if
+ * select_thread_start_poll() return -1. The GPollFD array passed
+ * in must be identical to the one passed to select_thread_start_poll().
+ *
+ * The results of the poll are written into the GPollFD array passed in.
+ *
+ * Returns: number of file descriptors ready
+ */
+static int
+select_thread_collect_poll (GPollFD *ufds, guint nfds)
+{
+  gint i;
+  gint n_ready = 0;
+
+  SELECT_THREAD_LOCK ();
+
+  if (select_thread_state == WAITING) /* The poll completed */
+    {
+      for (i = 0; i < nfds; i++)
+        {
+          if (ufds[i].fd == -1)
+            continue;
+
+          g_assert (ufds[i].fd == current_pollfds[i].fd);
+          g_assert (ufds[i].events == current_pollfds[i].events);
+
+          if (current_pollfds[i].revents)
+            {
+              ufds[i].revents = current_pollfds[i].revents;
+              n_ready++;
+            }
+        }
+
+#ifdef G_ENABLE_DEBUG
+      if (_gdk_debug_flags & GDK_DEBUG_EVENTLOOP)
+        {
+          g_message ("EventLoop: Found ready file descriptors after waiting");
+          dump_poll_result (ufds, nfds);
+        }
+#endif
+    }
+
+  SELECT_THREAD_UNLOCK ();
+
+  return n_ready;
+}
+
+/************************************************************
+ *********             Main Loop Source             *********
+ ************************************************************/
+
+typedef struct _GdkMacosEventSource
+{
+  GSource     source;
+  GdkDisplay *display;
+} GdkMacosEventSource;
+
+gboolean
+_gdk_macos_event_source_check_pending (void)
+{
+  return current_events && current_events->head;
+}
+
+NSEvent *
+_gdk_macos_event_source_get_pending (void)
+{
+  NSEvent *event = NULL;
+
+  if (current_events)
+    event = g_queue_pop_tail (current_events);
+
+  return event;
+}
+
+static gboolean
+gdk_macos_event_source_prepare (GSource *source,
+                                gint    *timeout)
+{
+  GdkMacosEventSource *event_source = (GdkMacosEventSource *)source;
+  gboolean retval;
+
+  /* The prepare stage is the stage before the main loop starts polling
+   * and dispatching events. The autorelease poll is drained here for
+   * the preceding main loop iteration or, in case of the first iteration,
+   * for the operations carried out between event loop initialization and
+   * this first iteration.
+   *
+   * The autorelease poll must only be drained when the following conditions
+   * apply:
+   *  - We are at the base CFRunLoop level (indicated by current_loop_level),
+   *  - We are at the base g_main_loop level (indicated by
+   *    g_main_depth())
+   *  - We are at the base poll_func level (indicated by getting events).
+   *
+   * Messing with the autorelease pool at any level of nesting can cause access
+   * to deallocated memory because autorelease_pool is static and releasing a
+   * pool will cause all pools allocated inside of it to be released as well.
+   */
+  if (current_loop_level == 0 && g_main_depth() == 0 && getting_events == 0)
+    {
+      if (autorelease_pool)
+        [autorelease_pool drain];
+
+      autorelease_pool = [[NSAutoreleasePool alloc] init];
+    }
+
+  *timeout = -1;
+
+  if (event_source->display->event_pause_count > 0)
+    retval = _gdk_event_queue_find_first (event_source->display) != NULL;
+  else
+    retval = (_gdk_event_queue_find_first (event_source->display) != NULL ||
+              _gdk_macos_event_source_check_pending ());
+
+  return retval;
+}
+
+static gboolean
+gdk_macos_event_source_check (GSource *source)
+{
+  GdkMacosEventSource *event_source = (GdkMacosEventSource *)source;
+  gboolean retval;
+
+  if (event_source->display->event_pause_count > 0)
+    retval = _gdk_event_queue_find_first (event_source->display) != NULL;
+  else
+    retval = (_gdk_event_queue_find_first (event_source->display) != NULL ||
+              _gdk_macos_event_source_check_pending ());
+
+  return retval;
+}
+
+static gboolean
+gdk_macos_event_source_dispatch (GSource     *source,
+                                 GSourceFunc  callback,
+                                 gpointer     user_data)
+{
+  GdkMacosEventSource *event_source = (GdkMacosEventSource *)source;
+  GdkEvent *event;
+
+  _gdk_macos_display_queue_events (GDK_MACOS_DISPLAY (event_source->display));
+
+  event = _gdk_event_unqueue (event_source->display);
+
+  if (event)
+    {
+      _gdk_event_emit (event);
+
+      gdk_event_unref (event);
+    }
+
+  return TRUE;
+}
+
+static void
+gdk_macos_event_source_finalize (GSource *source)
+{
+  GdkMacosEventSource *event_source = (GdkMacosEventSource *)source;
+
+  g_clear_object (&event_source->display);
+}
+
+static GSourceFuncs event_funcs = {
+  gdk_macos_event_source_prepare,
+  gdk_macos_event_source_check,
+  gdk_macos_event_source_dispatch,
+  gdk_macos_event_source_finalize,
+};
+
+/************************************************************
+ *********             Our Poll Function            *********
+ ************************************************************/
+
+static gint
+poll_func (GPollFD *ufds,
+           guint    nfds,
+           gint     timeout_)
+{
+  NSEvent *event;
+  NSDate *limit_date;
+  gint n_ready;
+
+  static GPollFD *last_ufds;
+
+  last_ufds = ufds;
+
+  n_ready = select_thread_start_poll (ufds, nfds, timeout_);
+  if (n_ready > 0)
+    timeout_ = 0;
+
+  if (timeout_ == -1)
+    limit_date = [NSDate distantFuture];
+  else if (timeout_ == 0)
+    limit_date = [NSDate distantPast];
+  else
+    limit_date = [NSDate dateWithTimeIntervalSinceNow:timeout_/1000.0];
+
+  getting_events++;
+  event = [NSApp nextEventMatchingMask: NSEventMaskAny
+                             untilDate: limit_date
+                                inMode: NSDefaultRunLoopMode
+                               dequeue: YES];
+  getting_events--;
+
+  /* We check if last_ufds did not change since the time this function was
+   * called. It is possible that a recursive main loop (and thus recursive
+   * invocation of this poll function) is triggered while in
+   * nextEventMatchingMask:. If during that time new fds are added,
+   * the cached fds array might be replaced in g_main_context_iterate().
+   * So, we should avoid accessing the old fd array (still pointed at by
+   * ufds) here in that case, since it might have been freed. We avoid this
+   * by not calling the collect stage.
+   */
+  if (last_ufds == ufds && n_ready < 0)
+    n_ready = select_thread_collect_poll (ufds, nfds);
+
+  if (event &&
+      [event type] == NSEventTypeApplicationDefined &&
+      [event subtype] == GDK_MACOS_EVENT_SUBTYPE_EVENTLOOP)
+    {
+      /* Just used to wake us up; if an event and a FD arrived at the same
+       * time; could have come from a previous iteration in some cases,
+       * but the spurious wake up is harmless if a little inefficient.
+       */
+      event = NULL;
+    }
+
+  if (event)
+    {
+      if (!current_events)
+        current_events = g_queue_new ();
+      g_queue_push_head (current_events, [event retain]);
+    }
+
+  return n_ready;
+}
+
+/************************************************************
+ *********  Running the main loop out of CFRunLoop  *********
+ ************************************************************/
+
+/* Wrapper around g_main_context_query() that handles reallocating
+ * run_loop_pollfds up to the proper size
+ */
+static gint
+query_main_context (GMainContext *context,
+                    int           max_priority,
+                    int          *timeout)
+{
+  gint nfds;
+
+  if (!run_loop_pollfds)
+    {
+      run_loop_pollfds_size = RUN_LOOP_POLLFDS_INITIAL_SIZE;
+      run_loop_pollfds = g_new (GPollFD, run_loop_pollfds_size);
+    }
+
+  while ((nfds = g_main_context_query (context, max_priority, timeout,
+                                       run_loop_pollfds,
+                                       run_loop_pollfds_size)) > run_loop_pollfds_size)
+    {
+      g_free (run_loop_pollfds);
+      run_loop_pollfds_size = nfds;
+      run_loop_pollfds = g_new (GPollFD, nfds);
+    }
+
+  return nfds;
+}
+
+static void
+run_loop_entry (void)
+{
+  if (acquired_loop_level == -1)
+    {
+      if (g_main_context_acquire (NULL))
+        {
+          GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Beginning tracking run loop activity"));
+          acquired_loop_level = current_loop_level;
+        }
+      else
+        {
+          /* If we fail to acquire the main context, that means someone is iterating
+           * the main context in a different thread; we simply wait until this loop
+           * exits and then try again at next entry. In general, iterating the loop
+           * from a different thread is rare: it is only possible when GDK threading
+           * is initialized and is not frequently used even then. So, we hope that
+           * having GLib main loop iteration blocked in the combination of that and
+           * a native modal operation is a minimal problem. We could imagine using a
+           * thread that does g_main_context_wait() and then wakes us back up, but
+           * the gain doesn't seem worth the complexity.
+           */
+          GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Can't acquire main loop; skipping tracking run loop activity"));
+        }
+    }
+}
+
+static void
+run_loop_before_timers (void)
+{
+}
+
+static void
+run_loop_before_sources (void)
+{
+  GMainContext *context = g_main_context_default ();
+  gint max_priority;
+  gint nfds;
+
+  /* Before we let the CFRunLoop process sources, we want to check if there
+   * are any pending GLib main loop sources more urgent than
+   * G_PRIORITY_DEFAULT that need to be dispatched. (We consider all activity
+   * from the CFRunLoop to have a priority of G_PRIORITY_DEFAULT.) If no
+   * sources are processed by the CFRunLoop, then processing will continue
+   * on to the BeforeWaiting stage where we check for lower priority sources.
+   */
+
+  g_main_context_prepare (context, &max_priority);
+  max_priority = MIN (max_priority, G_PRIORITY_DEFAULT);
+
+  /* We ignore the timeout that query_main_context () returns since we'll
+   * always query again before waiting.
+   */
+  nfds = query_main_context (context, max_priority, NULL);
+
+  if (nfds)
+    old_poll_func (run_loop_pollfds, nfds, 0);
+
+  if (g_main_context_check (context, max_priority, run_loop_pollfds, nfds))
+    {
+      GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Dispatching high priority sources"));
+      g_main_context_dispatch (context);
+    }
+}
+
+static void
+dummy_timer_callback (CFRunLoopTimerRef  timer,
+                      void              *info)
+{
+  /* Nothing; won't normally even be called */
+}
+
+static void
+run_loop_before_waiting (void)
+{
+  GMainContext *context = g_main_context_default ();
+  gint timeout;
+  gint n_ready;
+
+  /* At this point, the CFRunLoop is ready to wait. We start a GMain loop
+   * iteration by calling the check() and query() stages. We start a
+   * poll, and if it doesn't complete immediately we let the run loop
+   * go ahead and sleep. Before doing that, if there was a timeout from
+   * GLib, we set up a CFRunLoopTimer to wake us up.
+   */
+
+  g_main_context_prepare (context, &run_loop_max_priority);
+
+  run_loop_n_pollfds = query_main_context (context, run_loop_max_priority, &timeout);
+
+  n_ready = select_thread_start_poll (run_loop_pollfds, run_loop_n_pollfds, timeout);
+
+  if (n_ready > 0 || timeout == 0)
+    {
+      /* We have stuff to do, no sleeping allowed! */
+      CFRunLoopWakeUp (main_thread_run_loop);
+    }
+  else if (timeout > 0)
+    {
+      /* We need to get the run loop to break out of its wait when our timeout
+       * expires. We do this by adding a dummy timer that we'll remove immediately
+       * after the wait wakes up.
+       */
+      GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Adding timer to wake us up in %d milliseconds", timeout));
+
+      run_loop_timer = CFRunLoopTimerCreate (NULL, /* allocator */
+                                             CFAbsoluteTimeGetCurrent () + timeout / 1000.,
+                                             0, /* interval (0=does not repeat) */
+                                             0, /* flags */
+                                             0, /* order (priority) */
+                                             dummy_timer_callback,
+                                             NULL);
+
+      CFRunLoopAddTimer (main_thread_run_loop, run_loop_timer, kCFRunLoopCommonModes);
+    }
+
+  run_loop_polling_async = n_ready < 0;
+}
+
+static void
+run_loop_after_waiting (void)
+{
+  GMainContext *context = g_main_context_default ();
+
+  /* After sleeping, we finish of the GMain loop iteratin started in before_waiting()
+   * by doing the check() and dispatch() stages.
+   */
+
+  if (run_loop_timer)
+    {
+      CFRunLoopRemoveTimer (main_thread_run_loop, run_loop_timer, kCFRunLoopCommonModes);
+      CFRelease (run_loop_timer);
+      run_loop_timer = NULL;
+    }
+
+  if (run_loop_polling_async)
+    {
+      select_thread_collect_poll (run_loop_pollfds, run_loop_n_pollfds);
+      run_loop_polling_async = FALSE;
+    }
+
+  if (g_main_context_check (context, run_loop_max_priority, run_loop_pollfds, run_loop_n_pollfds))
+    {
+      GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Dispatching after waiting"));
+      g_main_context_dispatch (context);
+    }
+}
+
+static void
+run_loop_exit (void)
+{
+  /* + 1 because we decrement current_loop_level separately in observer_callback() */
+  if ((current_loop_level + 1) == acquired_loop_level)
+    {
+      g_main_context_release (NULL);
+      acquired_loop_level = -1;
+      GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Ended tracking run loop activity"));
+    }
+}
+
+static void
+run_loop_observer_callback (CFRunLoopObserverRef observer,
+                            CFRunLoopActivity    activity,
+                            void                *info)
+{
+  switch (activity)
+    {
+    case kCFRunLoopEntry:
+      current_loop_level++;
+      break;
+    case kCFRunLoopExit:
+      g_return_if_fail (current_loop_level > 0);
+      current_loop_level--;
+      break;
+    case kCFRunLoopBeforeTimers:
+    case kCFRunLoopBeforeSources:
+    case kCFRunLoopBeforeWaiting:
+    case kCFRunLoopAfterWaiting:
+    case kCFRunLoopAllActivities:
+    default:
+      break;
+    }
+
+  if (getting_events > 0) /* Activity we triggered */
+    return;
+
+  switch (activity)
+    {
+    case kCFRunLoopEntry:
+      run_loop_entry ();
+      break;
+    case kCFRunLoopBeforeTimers:
+      run_loop_before_timers ();
+      break;
+    case kCFRunLoopBeforeSources:
+      run_loop_before_sources ();
+      break;
+    case kCFRunLoopBeforeWaiting:
+      run_loop_before_waiting ();
+      break;
+    case kCFRunLoopAfterWaiting:
+      run_loop_after_waiting ();
+      break;
+    case kCFRunLoopExit:
+      run_loop_exit ();
+      break;
+    case kCFRunLoopAllActivities:
+      /* TODO: Do most of the above? */
+    default:
+      break;
+    }
+}
+
+/************************************************************/
+
+GSource *
+_gdk_macos_event_source_new (GdkMacosDisplay *display)
+{
+  CFRunLoopObserverRef observer;
+  GdkMacosEventSource *event_source;
+  GSource *source;
+
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
+
+  /* Hook into the GLib main loop */
+
+  event_poll_fd.events = G_IO_IN;
+  event_poll_fd.fd = -1;
+
+  source = g_source_new (&event_funcs, sizeof (GdkMacosEventSource));
+  g_source_set_name (source, "GDK Quartz event source");
+  g_source_add_poll (source, &event_poll_fd);
+  g_source_set_priority (source, GDK_PRIORITY_EVENTS);
+  g_source_set_can_recurse (source, TRUE);
+
+  old_poll_func = g_main_context_get_poll_func (NULL);
+  g_main_context_set_poll_func (NULL, poll_func);
+
+  event_source = (GdkMacosEventSource *)source;
+  event_source->display = g_object_ref (GDK_DISPLAY (display));
+
+  /* Hook into the the CFRunLoop for the main thread */
+
+  main_thread_run_loop = CFRunLoopGetCurrent ();
+
+  observer = CFRunLoopObserverCreate (NULL, /* default allocator */
+                                      kCFRunLoopAllActivities,
+                                      true, /* repeats: not one-shot */
+                                      0, /* order (priority) */
+                                      run_loop_observer_callback,
+                                      NULL);
+
+  CFRunLoopAddObserver (main_thread_run_loop, observer, kCFRunLoopCommonModes);
+
+  /* Initialize our autorelease pool */
+  autorelease_pool = [[NSAutoreleasePool alloc] init];
+
+  return source;
+}
diff --git a/gdk/macos/gdkmacosglcontext-private.h b/gdk/macos/gdkmacosglcontext-private.h
new file mode 100644 (file)
index 0000000..e976939
--- /dev/null
@@ -0,0 +1,60 @@
+/* gdkmacosglcontext-private.h
+ *
+ * Copyright (C) 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GDK_MACOS_GL_CONTEXT_PRIVATE_H__
+#define __GDK_MACOS_GL_CONTEXT_PRIVATE_H__
+
+#include "gdkglcontextprivate.h"
+#include "gdkdisplayprivate.h"
+#include "gdksurface.h"
+#include "gdkinternals.h"
+
+#include "gdkmacosglcontext.h"
+#include "gdkmacossurface.h"
+
+#import <OpenGL/OpenGL.h>
+#import <OpenGL/gl.h>
+#import <AppKit/AppKit.h>
+
+G_BEGIN_DECLS
+
+struct _GdkMacosGLContext
+{
+  GdkGLContext parent_instance;
+
+  G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+  NSOpenGLContext *gl_context;
+  G_GNUC_END_IGNORE_DEPRECATIONS
+
+  gboolean is_attached;
+};
+
+struct _GdkMacosGLContextClass
+{
+  GdkGLContextClass parent_class;
+};
+
+GdkGLContext *_gdk_macos_gl_context_new          (GdkMacosSurface    *surface,
+                                                  gboolean            attached,
+                                                  GdkGLContext       *share,
+                                                  GError            **error);
+gboolean      _gdk_macos_gl_context_make_current (GdkMacosGLContext  *self);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_GL_CONTEXT_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacosglcontext.c b/gdk/macos/gdkmacosglcontext.c
new file mode 100644 (file)
index 0000000..0d1e03e
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "gdkmacosglcontext-private.h"
+#include "gdkmacossurface-private.h"
+
+#include "gdkinternals.h"
+#include "gdkintl.h"
+
+G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+
+G_DEFINE_TYPE (GdkMacosGLContext, gdk_macos_gl_context, GDK_TYPE_GL_CONTEXT)
+
+static void
+gdk_macos_gl_context_end_frame (GdkDrawContext *context,
+                                cairo_region_t *painted)
+{
+  GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);
+
+  g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
+
+  [self->gl_context flushBuffer];
+}
+
+static void
+gdk_macos_gl_context_dispose (GObject *gobject)
+{
+  GdkMacosGLContext *context_macos = GDK_MACOS_GL_CONTEXT (gobject);
+
+  if (context_macos->gl_context != NULL)
+    {
+      [context_macos->gl_context clearDrawable];
+      [context_macos->gl_context release];
+      context_macos->gl_context = NULL;
+    }
+
+  G_OBJECT_CLASS (gdk_macos_gl_context_parent_class)->dispose (gobject);
+}
+
+static void
+gdk_macos_gl_context_class_init (GdkMacosGLContextClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
+
+  object_class->dispose = gdk_macos_gl_context_dispose;
+
+  draw_context_class->end_frame = gdk_macos_gl_context_end_frame;
+}
+
+static void
+gdk_macos_gl_context_init (GdkMacosGLContext *self)
+{
+}
+
+GdkGLContext *
+_gdk_macos_gl_context_new (GdkMacosSurface  *surface,
+                           gboolean          attached,
+                           GdkGLContext     *share,
+                           GError          **error)
+{
+  static const NSOpenGLPixelFormatAttribute attrs[] = {
+    NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
+    NSOpenGLPFADoubleBuffer,
+    NSOpenGLPFAColorSize, 24,
+    NSOpenGLPFAAlphaSize, 8,
+    0
+  };
+
+  NSOpenGLPixelFormat *format;
+  GdkMacosGLContext *context = NULL;
+  NSOpenGLContext *ctx;
+  GdkDisplay *display;
+  NSView *nsview;
+  GLint sync_to_framerate = 1;
+
+  g_return_val_if_fail (GDK_IS_MACOS_SURFACE (surface), NULL);
+  g_return_val_if_fail (!share || GDK_IS_MACOS_GL_CONTEXT (share), NULL);
+
+  display = gdk_surface_get_display (GDK_SURFACE (surface));
+
+  if (!(format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]))
+    {
+      g_set_error_literal (error,
+                           GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("Unable to create a GL pixel format"));
+      goto failure;
+    }
+
+  ctx = [[NSOpenGLContext alloc] initWithFormat:format
+                                 shareContext:share ? GDK_MACOS_GL_CONTEXT (share)->gl_context : nil];
+  if (ctx == NULL)
+    {
+      g_set_error_literal (error,
+                           GDK_GL_ERROR,
+                           GDK_GL_ERROR_NOT_AVAILABLE,
+                           _("Unable to create a GL context"));
+      goto failure;
+    }
+
+  nsview = _gdk_macos_surface_get_view (surface);
+  [nsview setWantsBestResolutionOpenGLSurface:YES];
+  [ctx setValues:&sync_to_framerate forParameter:NSOpenGLCPSwapInterval];
+  [ctx setView:nsview];
+
+  GDK_NOTE (OPENGL,
+            g_print ("Created NSOpenGLContext[%p]\n", ctx));
+
+  context = g_object_new (GDK_TYPE_MACOS_GL_CONTEXT,
+                          "surface", surface,
+                          "shared-context", share,
+                          NULL);
+
+  context->gl_context = ctx;
+  context->is_attached = attached;
+
+failure:
+  if (format != NULL)
+    [format release];
+
+  return GDK_GL_CONTEXT (context);
+}
+
+gboolean
+_gdk_macos_gl_context_make_current (GdkMacosGLContext *self)
+{
+  g_return_val_if_fail (GDK_IS_MACOS_GL_CONTEXT (self), FALSE);
+
+  [self->gl_context makeCurrentContext];
+
+  return TRUE;
+}
+
+G_GNUC_END_IGNORE_DEPRECATIONS
diff --git a/gdk/macos/gdkmacosglcontext.h b/gdk/macos/gdkmacosglcontext.h
new file mode 100644 (file)
index 0000000..e4add89
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_GL_CONTEXT_H__
+#define __GDK_MACOS_GL_CONTEXT_H__
+
+#if !defined (__GDKMACOS_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gdk/macos/gdkmacos.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_MACOS_GL_CONTEXT    (gdk_macos_gl_context_get_type ())
+#define GDK_MACOS_GL_CONTEXT(obj)    (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_MACOS_GL_CONTEXT, GdkMacosGLContext))
+#define GDK_IS_MACOS_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_MACOS_GL_CONTEXT))
+
+typedef struct _GdkMacosGLContext      GdkMacosGLContext;
+typedef struct _GdkMacosGLContextClass GdkMacosGLContextClass;
+
+GDK_AVAILABLE_IN_ALL
+GType gdk_macos_gl_context_get_type (void) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_GL_CONTEXT_H__ */
diff --git a/gdk/macos/gdkmacoskeymap-private.h b/gdk/macos/gdkmacoskeymap-private.h
new file mode 100644 (file)
index 0000000..34ff21b
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_KEYMAP_PRIVATE_H__
+#define __GDK_MACOS_KEYMAP_PRIVATE_H__
+
+#include <AppKit/AppKit.h>
+
+#include "gdkmacosdisplay.h"
+#include "gdkmacoskeymap.h"
+
+G_BEGIN_DECLS
+
+GdkMacosKeymap *_gdk_macos_keymap_new            (GdkMacosDisplay *display);
+GdkEventType    _gdk_macos_keymap_get_event_type (NSEvent         *event);
+gboolean        _gdk_macos_keymap_is_modifier    (guint            keycode);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_KEYMAP_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacoskeymap.c b/gdk/macos/gdkmacoskeymap.c
new file mode 100644 (file)
index 0000000..c638c75
--- /dev/null
@@ -0,0 +1,698 @@
+/*
+ * Copyright © 2000-2020 Red Hat, Inc.
+ * Copyright © 2005 Imendio AB
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+/* Some parts of this code come from quartzKeyboard.c,
+ * from the Apple X11 Server.
+ *
+ * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+ *
+ *  Permission is hereby granted, free of charge, to any person
+ *  obtaining a copy of this software and associated documentation files
+ *  (the "Software"), to deal in the Software without restriction,
+ *  including without limitation the rights to use, copy, modify, merge,
+ *  publish, distribute, sublicense, and/or sell copies of the Software,
+ *  and to permit persons to whom the Software is furnished to do so,
+ *  subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be
+ *  included in all copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *  NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ *  HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ *  DEALINGS IN THE SOFTWARE.
+ *
+ *  Except as contained in this notice, the name(s) of the above
+ *  copyright holders shall not be used in advertising or otherwise to
+ *  promote the sale, use or other dealings in this Software without
+ *  prior written authorization.
+ */
+
+#include "config.h"
+
+#include <AppKit/AppKit.h>
+#include <Carbon/Carbon.h>
+#include <gdk/gdk.h>
+
+#include "gdkkeysprivate.h"
+#include "gdkkeysyms.h"
+#include "gdkmacoskeymap-private.h"
+
+struct _GdkMacosKeymap
+{
+  GdkKeymap parent_instance;
+};
+
+struct _GdkMacosKeymapClass
+{
+  GdkKeymapClass parent_instance;
+};
+
+G_DEFINE_TYPE (GdkMacosKeymap, gdk_macos_keymap, GDK_TYPE_KEYMAP)
+
+/* This is a table of all keyvals. Each keycode gets KEYVALS_PER_KEYCODE entries.
+ * TThere is 1 keyval per modifier (Nothing, Shift, Alt, Shift+Alt);
+ */
+static guint *keyval_array = NULL;
+
+#define NUM_KEYCODES 128
+#define KEYVALS_PER_KEYCODE 4
+#define GET_KEYVAL(keycode, group, level) \
+  (keyval_array[(keycode * KEYVALS_PER_KEYCODE + group * 2 + level)])
+
+const static struct {
+  guint keycode;
+  guint keyval;
+  unsigned int modmask; /* So we can tell when a mod key is pressed/released */
+} modifier_keys[] = {
+  {  54, GDK_KEY_Meta_R,    NSEventModifierFlagCommand },
+  {  55, GDK_KEY_Meta_L,    NSEventModifierFlagCommand },
+  {  56, GDK_KEY_Shift_L,   NSEventModifierFlagShift },
+  {  57, GDK_KEY_Caps_Lock, NSEventModifierFlagCapsLock },
+  {  58, GDK_KEY_Alt_L,     NSEventModifierFlagOption },
+  {  59, GDK_KEY_Control_L, NSEventModifierFlagControl },
+  {  60, GDK_KEY_Shift_R,   NSEventModifierFlagShift },
+  {  61, GDK_KEY_Alt_R,     NSEventModifierFlagOption },
+  {  62, GDK_KEY_Control_R, NSEventModifierFlagControl }
+};
+
+const static struct {
+  guint keycode;
+  guint keyval;
+} function_keys[] = {
+  { 122, GDK_KEY_F1 },
+  { 120, GDK_KEY_F2 },
+  {  99, GDK_KEY_F3 },
+  { 118, GDK_KEY_F4 },
+  {  96, GDK_KEY_F5 },
+  {  97, GDK_KEY_F6 },
+  {  98, GDK_KEY_F7 },
+  { 100, GDK_KEY_F8 },
+  { 101, GDK_KEY_F9 },
+  { 109, GDK_KEY_F10 },
+  { 103, GDK_KEY_F11 },
+  { 111, GDK_KEY_F12 },
+  { 105, GDK_KEY_F13 },
+  { 107, GDK_KEY_F14 },
+  { 113, GDK_KEY_F15 },
+  { 106, GDK_KEY_F16 }
+};
+
+const static struct {
+  guint keycode;
+  guint normal_keyval, keypad_keyval;
+} known_numeric_keys[] = {
+  { 65, GDK_KEY_period, GDK_KEY_KP_Decimal },
+  { 67, GDK_KEY_asterisk, GDK_KEY_KP_Multiply },
+  { 69, GDK_KEY_plus, GDK_KEY_KP_Add },
+  { 75, GDK_KEY_slash, GDK_KEY_KP_Divide },
+  { 76, GDK_KEY_Return, GDK_KEY_KP_Enter },
+  { 78, GDK_KEY_minus, GDK_KEY_KP_Subtract },
+  { 81, GDK_KEY_equal, GDK_KEY_KP_Equal },
+  { 82, GDK_KEY_0, GDK_KEY_KP_0 },
+  { 83, GDK_KEY_1, GDK_KEY_KP_1 },
+  { 84, GDK_KEY_2, GDK_KEY_KP_2 },
+  { 85, GDK_KEY_3, GDK_KEY_KP_3 },
+  { 86, GDK_KEY_4, GDK_KEY_KP_4 },
+  { 87, GDK_KEY_5, GDK_KEY_KP_5 },
+  { 88, GDK_KEY_6, GDK_KEY_KP_6 },
+  { 89, GDK_KEY_7, GDK_KEY_KP_7 },
+  { 91, GDK_KEY_8, GDK_KEY_KP_8 },
+  { 92, GDK_KEY_9, GDK_KEY_KP_9 }
+};
+
+/* These values aren't covered by gdk_unicode_to_keyval */
+const static struct {
+  gunichar ucs_value;
+  guint keyval;
+} special_ucs_table [] = {
+  { 0x0001, GDK_KEY_Home },
+  { 0x0003, GDK_KEY_Return },
+  { 0x0004, GDK_KEY_End },
+  { 0x0008, GDK_KEY_BackSpace },
+  { 0x0009, GDK_KEY_Tab },
+  { 0x000b, GDK_KEY_Page_Up },
+  { 0x000c, GDK_KEY_Page_Down },
+  { 0x000d, GDK_KEY_Return },
+  { 0x001b, GDK_KEY_Escape },
+  { 0x001c, GDK_KEY_Left },
+  { 0x001d, GDK_KEY_Right },
+  { 0x001e, GDK_KEY_Up },
+  { 0x001f, GDK_KEY_Down },
+  { 0x007f, GDK_KEY_Delete },
+  { 0xf027, GDK_KEY_dead_acute },
+  { 0xf060, GDK_KEY_dead_grave },
+  { 0xf300, GDK_KEY_dead_grave },
+  { 0xf0b4, GDK_KEY_dead_acute },
+  { 0xf301, GDK_KEY_dead_acute },
+  { 0xf385, GDK_KEY_dead_acute },
+  { 0xf05e, GDK_KEY_dead_circumflex },
+  { 0xf2c6, GDK_KEY_dead_circumflex },
+  { 0xf302, GDK_KEY_dead_circumflex },
+  { 0xf07e, GDK_KEY_dead_tilde },
+  { 0xf2dc, GDK_KEY_dead_tilde },
+  { 0xf303, GDK_KEY_dead_tilde },
+  { 0xf342, GDK_KEY_dead_perispomeni },
+  { 0xf0af, GDK_KEY_dead_macron },
+  { 0xf304, GDK_KEY_dead_macron },
+  { 0xf2d8, GDK_KEY_dead_breve },
+  { 0xf306, GDK_KEY_dead_breve },
+  { 0xf2d9, GDK_KEY_dead_abovedot },
+  { 0xf307, GDK_KEY_dead_abovedot },
+  { 0xf0a8, GDK_KEY_dead_diaeresis },
+  { 0xf308, GDK_KEY_dead_diaeresis },
+  { 0xf2da, GDK_KEY_dead_abovering },
+  { 0xf30A, GDK_KEY_dead_abovering },
+  { 0xf022, GDK_KEY_dead_doubleacute },
+  { 0xf2dd, GDK_KEY_dead_doubleacute },
+  { 0xf30B, GDK_KEY_dead_doubleacute },
+  { 0xf2c7, GDK_KEY_dead_caron },
+  { 0xf30C, GDK_KEY_dead_caron },
+  { 0xf0be, GDK_KEY_dead_cedilla },
+  { 0xf327, GDK_KEY_dead_cedilla },
+  { 0xf2db, GDK_KEY_dead_ogonek },
+  { 0xf328, GDK_KEY_dead_ogonek },
+  { 0xfe5d, GDK_KEY_dead_iota },
+  { 0xf323, GDK_KEY_dead_belowdot },
+  { 0xf309, GDK_KEY_dead_hook },
+  { 0xf31B, GDK_KEY_dead_horn },
+  { 0xf02d, GDK_KEY_dead_stroke },
+  { 0xf335, GDK_KEY_dead_stroke },
+  { 0xf336, GDK_KEY_dead_stroke },
+  { 0xf313, GDK_KEY_dead_abovecomma },
+  /*  { 0xf313, GDK_KEY_dead_psili }, */
+  { 0xf314, GDK_KEY_dead_abovereversedcomma },
+  /*  { 0xf314, GDK_KEY_dead_dasia }, */
+  { 0xf30F, GDK_KEY_dead_doublegrave },
+  { 0xf325, GDK_KEY_dead_belowring },
+  { 0xf2cd, GDK_KEY_dead_belowmacron },
+  { 0xf331, GDK_KEY_dead_belowmacron },
+  { 0xf32D, GDK_KEY_dead_belowcircumflex },
+  { 0xf330, GDK_KEY_dead_belowtilde },
+  { 0xf32E, GDK_KEY_dead_belowbreve },
+  { 0xf324, GDK_KEY_dead_belowdiaeresis },
+  { 0xf311, GDK_KEY_dead_invertedbreve },
+  { 0xf02c, GDK_KEY_dead_belowcomma },
+  { 0xf326, GDK_KEY_dead_belowcomma }
+};
+
+static void
+gdk_macos_keymap_update (GdkMacosKeymap *self)
+{
+  const void *chr_data = NULL;
+  guint *p;
+  int i;
+
+  TISInputSourceRef new_layout = TISCopyCurrentKeyboardLayoutInputSource ();
+  CFDataRef layout_data_ref;
+
+  g_free (keyval_array);
+  keyval_array = g_new0 (guint, NUM_KEYCODES * KEYVALS_PER_KEYCODE);
+
+  layout_data_ref = (CFDataRef)TISGetInputSourceProperty (new_layout, kTISPropertyUnicodeKeyLayoutData);
+
+  if (layout_data_ref)
+    chr_data = CFDataGetBytePtr (layout_data_ref);
+
+  if (chr_data == NULL)
+    {
+      g_error ("cannot get keyboard layout data");
+      return;
+    }
+
+  for (i = 0; i < NUM_KEYCODES; i++)
+    {
+      int j;
+      UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
+      UniChar chars[4];
+      UniCharCount nChars;
+
+      p = keyval_array + i * KEYVALS_PER_KEYCODE;
+
+      for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
+        {
+          UInt32 state = 0;
+          OSStatus err;
+          UInt16 key_code;
+          UniChar uc;
+
+          key_code = modifiers[j] | i;
+          err = UCKeyTranslate (chr_data, i, kUCKeyActionDisplay,
+                                (modifiers[j] >> 8) & 0xFF,
+                                LMGetKbdType(),
+                                0,
+                                &state, 4, &nChars, chars);
+
+          /* FIXME: Theoretically, we can get multiple UTF-16
+           * values; we should convert them to proper unicode and
+           * figure out whether there are really keyboard layouts
+           * that give us more than one character for one
+           * keypress.
+           */
+          if (err == noErr && nChars == 1)
+            {
+              int k;
+              gboolean found = FALSE;
+
+              /* A few <Shift><Option>keys return two characters,
+               * the first of which is U+00a0, which isn't
+               * interesting; so we return the second. More
+               * sophisticated handling is the job of a
+               * GtkIMContext.
+               *
+               * If state isn't zero, it means that it's a dead
+               * key of some sort. Some of those are enumerated in
+               * the special_ucs_table with the high nibble set to
+               * f to push it into the private use range. Here we
+               * do the same.
+               */
+              if (state != 0)
+                chars[nChars - 1] |= 0xf000;
+              uc = chars[nChars - 1];
+
+              for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
+                {
+                  if (special_ucs_table[k].ucs_value == uc)
+                    {
+                      p[j] = special_ucs_table[k].keyval;
+                      found = TRUE;
+                      break;
+                    }
+                }
+
+              /* Special-case shift-tab since GTK+ expects
+               * GDK_KEY_ISO_Left_Tab for that.
+               */
+              if (found && p[j] == GDK_KEY_Tab && modifiers[j] == shiftKey)
+                p[j] = GDK_KEY_ISO_Left_Tab;
+
+              if (!found)
+                p[j] = gdk_unicode_to_keyval (uc);
+            }
+        }
+
+      if (p[3] == p[2])
+        p[3] = 0;
+      if (p[2] == p[1])
+        p[2] = 0;
+      if (p[1] == p[0])
+        p[1] = 0;
+      if (p[0] == p[2] &&
+          p[1] == p[3])
+        p[2] = p[3] = 0;
+    }
+
+  for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
+    {
+      p = keyval_array + modifier_keys[i].keycode * KEYVALS_PER_KEYCODE;
+
+      if (p[0] == 0 && p[1] == 0 &&
+          p[2] == 0 && p[3] == 0)
+        p[0] = modifier_keys[i].keyval;
+    }
+
+  for (i = 0; i < G_N_ELEMENTS (function_keys); i++)
+    {
+      p = keyval_array + function_keys[i].keycode * KEYVALS_PER_KEYCODE;
+
+      p[0] = function_keys[i].keyval;
+      p[1] = p[2] = p[3] = 0;
+    }
+
+  for (i = 0; i < G_N_ELEMENTS (known_numeric_keys); i++)
+    {
+      p = keyval_array + known_numeric_keys[i].keycode * KEYVALS_PER_KEYCODE;
+
+      if (p[0] == known_numeric_keys[i].normal_keyval)
+        p[0] = known_numeric_keys[i].keypad_keyval;
+    }
+
+  g_signal_emit_by_name (self, "keys-changed");
+}
+
+static PangoDirection
+gdk_macos_keymap_get_direction (GdkKeymap *keymap)
+{
+  return PANGO_DIRECTION_NEUTRAL;
+}
+
+static gboolean
+gdk_macos_keymap_have_bidi_layouts (GdkKeymap *keymap)
+{
+  return FALSE;
+}
+
+static gboolean
+gdk_macos_keymap_get_caps_lock_state (GdkKeymap *keymap)
+{
+  return FALSE;
+}
+
+static gboolean
+gdk_macos_keymap_get_num_lock_state (GdkKeymap *keymap)
+{
+  return FALSE;
+}
+
+static gboolean
+gdk_macos_keymap_get_scroll_lock_state (GdkKeymap *keymap)
+{
+  return FALSE;
+}
+
+static guint
+gdk_macos_keymap_lookup_key (GdkKeymap          *keymap,
+                             const GdkKeymapKey *key)
+{
+  GdkMacosKeymap *self = (GdkMacosKeymap *)keymap;
+
+  g_assert (GDK_IS_MACOS_KEYMAP (self));
+  g_assert (key != NULL);
+
+  return GET_KEYVAL (key->keycode, key->group, key->level);
+}
+
+static guint
+translate_keysym (guint            hardware_keycode,
+                  gint             group,
+                  GdkModifierType  state,
+                  gint            *effective_group,
+                  gint            *effective_level)
+{
+  gint level;
+  guint tmp_keyval;
+
+  level = (state & GDK_SHIFT_MASK) ? 1 : 0;
+
+  if (!(GET_KEYVAL (hardware_keycode, group, 0) || GET_KEYVAL (hardware_keycode, group, 1)) &&
+      (GET_KEYVAL (hardware_keycode, 0, 0) || GET_KEYVAL (hardware_keycode, 0, 1)))
+    group = 0;
+
+  if (!GET_KEYVAL (hardware_keycode, group, level) &&
+      GET_KEYVAL (hardware_keycode, group, 0))
+    level = 0;
+
+  tmp_keyval = GET_KEYVAL (hardware_keycode, group, level);
+
+  if (state & GDK_LOCK_MASK)
+    {
+      guint upper = gdk_keyval_to_upper (tmp_keyval);
+      if (upper != tmp_keyval)
+        tmp_keyval = upper;
+    }
+
+  if (effective_group)
+    *effective_group = group;
+  if (effective_level)
+    *effective_level = level;
+
+  return tmp_keyval;
+}
+
+static gboolean
+gdk_macos_keymap_get_entries_for_keyval (GdkKeymap *keymap,
+                                         guint      keyval,
+                                         GArray    *keys)
+{
+  gboolean ret = FALSE;
+
+  g_assert (GDK_IS_MACOS_KEYMAP (keymap));
+  g_assert (keys != NULL);
+
+  for (guint i = 0; i < NUM_KEYCODES * KEYVALS_PER_KEYCODE; i++)
+    {
+      GdkKeymapKey key;
+
+      if (keyval_array[i] != keyval)
+        continue;
+
+      key.keycode = i / KEYVALS_PER_KEYCODE;
+      key.group = (i % KEYVALS_PER_KEYCODE) >= 2;
+      key.level = i % 2;
+
+      g_array_append_val (keys, key);
+
+      ret = TRUE;
+    }
+
+  return ret;
+}
+
+static gboolean
+gdk_macos_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
+                                          guint          hardware_keycode,
+                                          GdkKeymapKey **keys,
+                                          guint        **keyvals,
+                                          gint          *n_entries)
+{
+  GArray *keys_array;
+  GArray *keyvals_array;
+  guint *p;
+  guint i;
+
+  g_assert (GDK_IS_MACOS_KEYMAP (keymap));
+  g_assert (keyvals != NULL);
+  g_assert (n_entries != NULL);
+
+  *keyvals = NULL;
+  *n_entries = 0;
+
+  if (hardware_keycode > NUM_KEYCODES)
+    return FALSE;
+
+  if (keys)
+    keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
+  else
+    keys_array = NULL;
+
+  if (keyvals)
+    keyvals_array = g_array_new (FALSE, FALSE, sizeof (guint));
+  else
+    keyvals_array = NULL;
+
+  p = keyval_array + hardware_keycode * KEYVALS_PER_KEYCODE;
+
+  for (i = 0; i < KEYVALS_PER_KEYCODE; i++)
+    {
+      if (!p[i])
+        continue;
+
+      (*n_entries)++;
+
+      if (keyvals_array)
+        g_array_append_val (keyvals_array, p[i]);
+
+      if (keys_array)
+        {
+          GdkKeymapKey key;
+
+          key.keycode = hardware_keycode;
+          key.group = i >= 2;
+          key.level = i % 2;
+
+          g_array_append_val (keys_array, key);
+        }
+    }
+
+  if (keys)
+    *keys = (GdkKeymapKey *)(gpointer)g_array_free (keys_array, FALSE);
+
+  if (keyvals)
+    *keyvals = (guint *)(gpointer)g_array_free (keyvals_array, FALSE);
+
+  return *n_entries > 0;
+}
+
+static gboolean
+gdk_macos_keymap_translate_keyboard_state (GdkKeymap       *keymap,
+                                           guint            hardware_keycode,
+                                           GdkModifierType  state,
+                                           gint             group,
+                                           guint           *keyval,
+                                           gint            *effective_group,
+                                           gint            *level,
+                                           GdkModifierType *consumed_modifiers)
+{
+  guint tmp_keyval;
+  GdkModifierType bit;
+
+  g_assert (GDK_IS_MACOS_KEYMAP (keymap));
+
+  if (keyval)
+    *keyval = 0;
+  if (effective_group)
+    *effective_group = 0;
+  if (level)
+    *level = 0;
+  if (consumed_modifiers)
+    *consumed_modifiers = 0;
+
+  if (hardware_keycode < 0 || hardware_keycode >= NUM_KEYCODES)
+    return FALSE;
+
+  tmp_keyval = translate_keysym (hardware_keycode, group, state, level, effective_group);
+
+  /* Check if modifiers modify the keyval */
+  if (consumed_modifiers)
+    {
+      guint tmp_modifiers = (state & GDK_MODIFIER_MASK);
+
+      for (bit = 1; bit <= tmp_modifiers; bit <<= 1)
+        {
+          if ((bit & tmp_modifiers) &&
+              translate_keysym (hardware_keycode, group, state & ~bit,
+                                NULL, NULL) == tmp_keyval)
+            tmp_modifiers &= ~bit;
+        }
+
+      *consumed_modifiers = tmp_modifiers;
+    }
+
+  if (keyval)
+    *keyval = tmp_keyval;
+
+  return TRUE;
+}
+
+static void
+input_sources_changed_notification (CFNotificationCenterRef  center,
+                                    void                    *observer,
+                                    CFStringRef              name,
+                                    const void              *object,
+                                    CFDictionaryRef          userInfo)
+{
+  GdkMacosKeymap *self = observer;
+
+  g_assert (GDK_IS_MACOS_KEYMAP (self));
+
+  gdk_macos_keymap_update (self);
+}
+
+static void
+gdk_macos_keymap_finalize (GObject *object)
+{
+  CFNotificationCenterRemoveObserver (CFNotificationCenterGetDistributedCenter (),
+                                      object,
+                                      CFSTR ("AppleSelectedInputSourcesChangedNotification"),
+                                      NULL);
+
+  G_OBJECT_CLASS (gdk_macos_keymap_parent_class)->finalize (object);
+}
+
+static void
+gdk_macos_keymap_class_init (GdkMacosKeymapClass *klass)
+{
+  GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gdk_macos_keymap_finalize;
+
+  keymap_class->get_caps_lock_state = gdk_macos_keymap_get_caps_lock_state;
+  keymap_class->get_direction = gdk_macos_keymap_get_direction;
+  keymap_class->get_entries_for_keycode = gdk_macos_keymap_get_entries_for_keycode;
+  keymap_class->get_entries_for_keyval = gdk_macos_keymap_get_entries_for_keyval;
+  keymap_class->get_num_lock_state = gdk_macos_keymap_get_num_lock_state;
+  keymap_class->get_scroll_lock_state = gdk_macos_keymap_get_scroll_lock_state;
+  keymap_class->have_bidi_layouts = gdk_macos_keymap_have_bidi_layouts;
+  keymap_class->lookup_key = gdk_macos_keymap_lookup_key;
+  keymap_class->translate_keyboard_state = gdk_macos_keymap_translate_keyboard_state;
+}
+
+static void
+gdk_macos_keymap_init (GdkMacosKeymap *self)
+{
+  CFNotificationCenterAddObserver (CFNotificationCenterGetDistributedCenter (),
+                                   self,
+                                   input_sources_changed_notification,
+                                   CFSTR ("AppleSelectedInputSourcesChangedNotification"),
+                                   NULL,
+                                   CFNotificationSuspensionBehaviorDeliverImmediately);
+  gdk_macos_keymap_update (self);
+}
+
+GdkMacosKeymap *
+_gdk_macos_keymap_new (GdkMacosDisplay *display)
+{
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
+
+  return g_object_new (GDK_TYPE_MACOS_KEYMAP,
+                       "display", display,
+                       NULL);
+}
+
+/* What sort of key event is this? Returns one of
+ * GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_NOTHING (should be ignored)
+ */
+GdkEventType
+_gdk_macos_keymap_get_event_type (NSEvent *event)
+{
+  unsigned short keycode;
+  unsigned int flags;
+
+  switch ((int)[event type])
+    {
+    case NSEventTypeKeyDown:
+      return GDK_KEY_PRESS;
+    case NSEventTypeKeyUp:
+      return GDK_KEY_RELEASE;
+    case NSEventTypeFlagsChanged:
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+
+  /* For flags-changed events, we have to find the special key that caused the
+   * event, and see if it's in the modifier mask. */
+  keycode = [event keyCode];
+  flags = [event modifierFlags];
+
+  for (guint i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
+    {
+      if (modifier_keys[i].keycode == keycode)
+        {
+          if (flags & modifier_keys[i].modmask)
+            return GDK_KEY_PRESS;
+          else
+            return GDK_KEY_RELEASE;
+        }
+    }
+
+  /* Some keypresses (eg: Expose' activations) seem to trigger flags-changed
+   * events for no good reason. Ignore them! */
+  return 0;
+}
+
+gboolean
+_gdk_macos_keymap_is_modifier (guint keycode)
+{
+  for (guint i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
+    {
+      if (modifier_keys[i].modmask == 0)
+        break;
+
+      if (modifier_keys[i].keycode == keycode)
+        return TRUE;
+    }
+
+  return FALSE;
+}
diff --git a/gdk/macos/gdkmacoskeymap.h b/gdk/macos/gdkmacoskeymap.h
new file mode 100644 (file)
index 0000000..6a8a7e2
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_KEYMAP_H__
+#define __GDK_MACOS_KEYMAP_H__
+
+#if !defined (__GDKMACOS_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gdk/macos/gdkmacos.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GdkMacosKeymap      GdkMacosKeymap;
+typedef struct _GdkMacosKeymapClass GdkMacosKeymapClass;
+
+#define GDK_TYPE_MACOS_KEYMAP       (gdk_macos_keymap_get_type())
+#define GDK_MACOS_KEYMAP(object)    (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_KEYMAP, GdkMacosKeymap))
+#define GDK_IS_MACOS_KEYMAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_KEYMAP))
+
+GDK_AVAILABLE_IN_ALL
+GType gdk_macos_keymap_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_KEYMAP_H__ */
diff --git a/gdk/macos/gdkmacosmonitor-private.h b/gdk/macos/gdkmacosmonitor-private.h
new file mode 100644 (file)
index 0000000..3c6f058
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_MONITOR_PRIVATE_H__
+#define __GDK_MACOS_MONITOR_PRIVATE_H__
+
+#include <AppKit/AppKit.h>
+
+#include "gdkmacosdisplay.h"
+#include "gdkmacosmonitor.h"
+
+#include "gdkmonitorprivate.h"
+
+G_BEGIN_DECLS
+
+GdkMacosMonitor   *_gdk_macos_monitor_new           (GdkMacosDisplay   *display,
+                                                     CGDirectDisplayID  screen_id);
+CGDirectDisplayID  _gdk_macos_monitor_get_screen_id (GdkMacosMonitor   *self);
+gboolean           _gdk_macos_monitor_reconfigure   (GdkMacosMonitor   *self);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_MONITOR_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacosmonitor.c b/gdk/macos/gdkmacosmonitor.c
new file mode 100644 (file)
index 0000000..ade7f0b
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include <gdk/gdk.h>
+#include <math.h>
+
+#include "gdkmacosdisplay-private.h"
+#include "gdkmacosmonitor-private.h"
+#include "gdkmacosutils-private.h"
+
+struct _GdkMacosMonitor
+{
+  GdkMonitor        parent_instance;
+  CGDirectDisplayID screen_id;
+  NSRect            workarea;
+  guint             has_opengl : 1;
+};
+
+struct _GdkMacosMonitorClass
+{
+  GdkMonitorClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkMacosMonitor, gdk_macos_monitor, GDK_TYPE_MONITOR)
+
+static void
+gdk_macos_monitor_get_workarea (GdkMonitor   *monitor,
+                                GdkRectangle *geometry)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  GdkMacosMonitor *self = (GdkMacosMonitor *)monitor;
+  int x,  y;
+
+  g_assert (GDK_IS_MACOS_MONITOR (self));
+  g_assert (geometry != NULL);
+
+  x = self->workarea.origin.x;
+  y = self->workarea.origin.y + self->workarea.size.height;
+
+  _gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (monitor->display),
+                                          x, y,
+                                          &x, &y);
+
+  geometry->x = x;
+  geometry->y = y;
+  geometry->width = self->workarea.size.width;
+  geometry->height = self->workarea.size.height;
+
+  GDK_END_MACOS_ALLOC_POOL;
+}
+
+static void
+gdk_macos_monitor_class_init (GdkMacosMonitorClass *klass)
+{
+  GdkMonitorClass *monitor_class = GDK_MONITOR_CLASS (klass);
+
+  monitor_class->get_workarea = gdk_macos_monitor_get_workarea;
+}
+
+static void
+gdk_macos_monitor_init (GdkMacosMonitor *self)
+{
+}
+
+static GdkSubpixelLayout
+GetSubpixelLayout (CGDirectDisplayID screen_id)
+{
+#if 0
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  GdkSubpixelLayout subpixel_layout = GDK_SUBPIXEL_LAYOUT_UNKNOWN;
+  io_service_t iosvc;
+  NSDictionary *dict;
+  guint layout;
+  gboolean rotation;
+
+  rotation = CGDisplayRotation (screen_id);
+  iosvc = CGDisplayIOServicePort (screen_id);
+  dict = (NSDictionary *)IODisplayCreateInfoDictionary (iosvc, kIODisplayOnlyPreferredName);
+  layout = [[dict objectForKey:@kDisplaySubPixelLayout] unsignedIntValue];
+
+  switch (layout)
+    {
+    case kDisplaySubPixelLayoutRGB:
+      if (rotation == 0.0)
+        subpixel_layout = GDK_SUBPIXEL_LAYOUT_HORIZONTAL_RGB;
+      else if (rotation == 90.0)
+        subpixel_layout = GDK_SUBPIXEL_LAYOUT_VERTICAL_RGB;
+      else if (rotation == 180.0 || rotation == -180.0)
+        subpixel_layout = GDK_SUBPIXEL_LAYOUT_HORIZONTAL_BGR;
+      else if (rotation == -90.0)
+        subpixel_layout = GDK_SUBPIXEL_LAYOUT_VERTICAL_BGR;
+      break;
+
+    case kDisplaySubPixelLayoutBGR:
+      if (rotation == 0.0)
+        subpixel_layout = GDK_SUBPIXEL_LAYOUT_HORIZONTAL_BGR;
+      else if (rotation == 90.0)
+        subpixel_layout = GDK_SUBPIXEL_LAYOUT_VERTICAL_BGR;
+      else if (rotation == 180.0 || rotation == -180.0)
+        subpixel_layout = GDK_SUBPIXEL_LAYOUT_HORIZONTAL_RGB;
+      else if (rotation == -90.0 || rotation == 270.0)
+        subpixel_layout = GDK_SUBPIXEL_LAYOUT_VERTICAL_RGB;
+      break;
+
+    default:
+      break;
+    }
+
+  GDK_END_MACOS_ALLOC_POOL;
+
+  return subpixel_layout;
+#endif
+
+  return GDK_SUBPIXEL_LAYOUT_UNKNOWN;
+}
+
+static char *
+GetLocalizedName (NSScreen *screen)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  NSString *str;
+  char *name;
+
+  g_assert (screen);
+
+  str = [screen localizedName];
+  name = g_strdup ([str UTF8String]);
+
+  GDK_END_MACOS_ALLOC_POOL;
+
+  return g_steal_pointer (&name);
+}
+
+static gchar *
+GetConnectorName (CGDirectDisplayID screen_id)
+{
+  guint unit = CGDisplayUnitNumber (screen_id);
+  return g_strdup_printf ("unit-%u", unit);
+}
+
+static NSScreen *
+find_screen (CGDirectDisplayID screen_id)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  NSScreen *screen = NULL;
+
+  for (id obj in [NSScreen screens])
+    {
+      if (screen_id == [[[obj deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue])
+        {
+          screen = (NSScreen *)obj;
+          break;
+        }
+    }
+
+  GDK_END_MACOS_ALLOC_POOL;
+
+  return screen;
+}
+
+gboolean
+_gdk_macos_monitor_reconfigure (GdkMacosMonitor *self)
+{
+  GdkSubpixelLayout subpixel_layout;
+  CGDisplayModeRef mode;
+  GdkMacosDisplay *display;
+  NSScreen *screen;
+  GdkRectangle geom;
+  gboolean has_opengl;
+  CGSize size;
+  CGRect bounds;
+  size_t width;
+  size_t pixel_width;
+  gchar *connector;
+  gchar *name;
+  int refresh_rate;
+  int scale_factor = 1;
+  int width_mm;
+  int height_mm;
+
+  g_return_val_if_fail (GDK_IS_MACOS_MONITOR (self), FALSE);
+
+  display = GDK_MACOS_DISPLAY (GDK_MONITOR (self)->display);
+
+  if (!(screen = find_screen (self->screen_id)) ||
+      !(mode = CGDisplayCopyDisplayMode (self->screen_id)))
+    return FALSE;
+
+  size = CGDisplayScreenSize (self->screen_id);
+  bounds = [screen frame];
+  width = CGDisplayModeGetWidth (mode);
+  pixel_width = CGDisplayModeGetPixelWidth (mode);
+  has_opengl = CGDisplayUsesOpenGLAcceleration (self->screen_id);
+  subpixel_layout = GetSubpixelLayout (self->screen_id);
+  name = GetLocalizedName (screen);
+  connector = GetConnectorName (self->screen_id);
+
+  if (width != 0 && pixel_width != 0)
+    scale_factor = MAX (1, pixel_width / width);
+
+  width_mm = size.width;
+  height_mm = size.height;
+
+  geom.x = bounds.origin.x - display->min_x;
+  geom.y = display->height - bounds.origin.y - bounds.size.height + display->min_y;
+  geom.width = bounds.size.width;
+  geom.height = bounds.size.height;
+
+  /* We will often get 0 back from CGDisplayModeGetRefreshRate().  We
+   * can fallback by getting it from CoreVideo based on a CVDisplayLink
+   * setting (which is also used by the frame clock).
+   */
+  if (!(refresh_rate = CGDisplayModeGetRefreshRate (mode)))
+    refresh_rate = _gdk_macos_display_get_nominal_refresh_rate (display);
+
+  gdk_monitor_set_connector (GDK_MONITOR (self), connector);
+  gdk_monitor_set_model (GDK_MONITOR (self), name);
+  gdk_monitor_set_geometry (GDK_MONITOR (self), &geom);
+  gdk_monitor_set_physical_size (GDK_MONITOR (self), width_mm, height_mm);
+  gdk_monitor_set_scale_factor (GDK_MONITOR (self), scale_factor);
+  gdk_monitor_set_refresh_rate (GDK_MONITOR (self), refresh_rate);
+  gdk_monitor_set_subpixel_layout (GDK_MONITOR (self), GDK_SUBPIXEL_LAYOUT_UNKNOWN);
+
+  self->workarea = [screen visibleFrame];
+
+  /* We might be able to use this at some point to change which GSK renderer
+   * we use for surfaces on this monitor.  For example, it might be better
+   * to use cairo if we cannot use OpenGL (or it would be software) anyway.
+   * Presumably that is more common in cases where macOS is running under
+   * an emulator such as QEMU.
+   */
+  self->has_opengl = !!has_opengl;
+
+  CGDisplayModeRelease (mode);
+  g_free (name);
+  g_free (connector);
+
+  return TRUE;
+}
+
+GdkMacosMonitor *
+_gdk_macos_monitor_new (GdkMacosDisplay   *display,
+                        CGDirectDisplayID  screen_id)
+{
+  GdkMacosMonitor *self;
+
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
+
+  self = g_object_new (GDK_TYPE_MACOS_MONITOR,
+                       "display", display,
+                       NULL);
+
+  self->screen_id = screen_id;
+
+  _gdk_macos_monitor_reconfigure (self);
+
+  return g_steal_pointer (&self);
+}
+
+CGDirectDisplayID
+_gdk_macos_monitor_get_screen_id (GdkMacosMonitor *self)
+{
+  g_return_val_if_fail (GDK_IS_MACOS_MONITOR (self), 0);
+
+  return self->screen_id;
+}
diff --git a/gdk/macos/gdkmacosmonitor.h b/gdk/macos/gdkmacosmonitor.h
new file mode 100644 (file)
index 0000000..64b91f8
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_MONITOR_H__
+#define __GDK_MACOS_MONITOR_H__
+
+#if !defined (__GDKMACOS_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gdk/macos/gdkmacos.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GdkMacosMonitor      GdkMacosMonitor;
+typedef struct _GdkMacosMonitorClass GdkMacosMonitorClass;
+
+#define GDK_TYPE_MACOS_MONITOR       (gdk_macos_monitor_get_type())
+#define GDK_MACOS_MONITOR(object)    (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_MONITOR, GdkMacosMonitor))
+#define GDK_IS_MACOS_MONITOR(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_MONITOR))
+
+GDK_AVAILABLE_IN_ALL
+GType gdk_macos_monitor_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_MONITOR_H__ */
diff --git a/gdk/macos/gdkmacospopupsurface-private.h b/gdk/macos/gdkmacospopupsurface-private.h
new file mode 100644 (file)
index 0000000..8c63d4f
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_POPUP_SURFACE_PRIVATE_H__
+#define __GDK_MACOS_POPUP_SURFACE_PRIVATE_H__
+
+#include "gdkmacossurface-private.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GdkMacosPopupSurface      GdkMacosPopupSurface;
+typedef struct _GdkMacosPopupSurfaceClass GdkMacosPopupSurfaceClass;
+
+#define GDK_TYPE_MACOS_POPUP_SURFACE       (_gdk_macos_popup_surface_get_type())
+#define GDK_MACOS_POPUP_SURFACE(object)    (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_POPUP_SURFACE, GdkMacosPopupSurface))
+#define GDK_IS_MACOS_POPUP_SURFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_POPUP_SURFACE))
+
+GType            _gdk_macos_popup_surface_get_type           (void);
+GdkMacosSurface *_gdk_macos_popup_surface_new                (GdkMacosDisplay      *display,
+                                                              GdkSurface           *parent,
+                                                              GdkFrameClock        *frame_clock,
+                                                              int                   x,
+                                                              int                   y,
+                                                              int                   width,
+                                                              int                   height);
+void             _gdk_macos_popup_surface_attach_to_parent   (GdkMacosPopupSurface *self);
+void             _gdk_macos_popup_surface_detach_from_parent (GdkMacosPopupSurface *self);
+void             _gdk_macos_popup_surface_reposition         (GdkMacosPopupSurface *self);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_POPUP_SURFACE_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacospopupsurface.c b/gdk/macos/gdkmacospopupsurface.c
new file mode 100644 (file)
index 0000000..520a717
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#import "GdkMacosWindow.h"
+
+#include "gdkinternals.h"
+#include "gdkpopupprivate.h"
+
+#include "gdkmacosdisplay-private.h"
+#include "gdkmacospopupsurface-private.h"
+#include "gdkmacosutils-private.h"
+
+struct _GdkMacosPopupSurface
+{
+  GdkMacosSurface parent_instance;
+  GdkPopupLayout *layout;
+};
+
+struct _GdkMacosPopupSurfaceClass
+{
+  GdkMacosSurfaceClass parent_class;
+};
+
+static void
+gdk_macos_popup_surface_layout (GdkMacosPopupSurface *self,
+                                int                   width,
+                                int                   height,
+                                GdkPopupLayout       *layout)
+{
+  GdkRectangle final_rect;
+  int x, y;
+
+  g_assert (GDK_IS_MACOS_POPUP_SURFACE (self));
+  g_assert (layout != NULL);
+  g_assert (GDK_SURFACE (self)->parent);
+
+  if (layout != self->layout)
+    {
+      g_clear_pointer (&self->layout, gdk_popup_layout_unref);
+      self->layout = gdk_popup_layout_ref (layout);
+    }
+
+  gdk_surface_layout_popup_helper (GDK_SURFACE (self),
+                                   width,
+                                   height,
+                                   layout,
+                                   &final_rect);
+
+  gdk_surface_get_origin (GDK_SURFACE (self)->parent, &x, &y);
+
+  x += final_rect.x;
+  y += final_rect.y;
+
+  if (final_rect.width != GDK_SURFACE (self)->width ||
+      final_rect.height != GDK_SURFACE (self)->height)
+    _gdk_macos_surface_move_resize (GDK_MACOS_SURFACE (self),
+                                    x,
+                                    y,
+                                    final_rect.width,
+                                    final_rect.height);
+  else if (x != GDK_MACOS_SURFACE (self)->root_x ||
+           y != GDK_MACOS_SURFACE (self)->root_y)
+    _gdk_macos_surface_move (GDK_MACOS_SURFACE (self), x, y);
+  else
+    return;
+
+  gdk_surface_invalidate_rect (GDK_SURFACE (self), NULL);
+}
+
+static void
+show_popup (GdkMacosPopupSurface *self)
+{
+  _gdk_macos_surface_show (GDK_MACOS_SURFACE (self));
+}
+
+static void
+show_grabbing_popup (GdkSeat    *seat,
+                     GdkSurface *surface,
+                     gpointer    user_data)
+{
+  show_popup (GDK_MACOS_POPUP_SURFACE (surface));
+}
+
+static gboolean
+gdk_macos_popup_surface_present (GdkPopup       *popup,
+                                 int             width,
+                                 int             height,
+                                 GdkPopupLayout *layout)
+{
+  GdkMacosPopupSurface *self = (GdkMacosPopupSurface *)popup;
+
+  g_assert (GDK_IS_MACOS_POPUP_SURFACE (self));
+
+  gdk_macos_popup_surface_layout (self, width, height, layout);
+
+  GDK_MACOS_SURFACE (self)->did_initial_present = TRUE;
+
+  if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self)))
+    return TRUE;
+
+  if (GDK_SURFACE (self)->autohide)
+    {
+      GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (popup));
+      GdkSeat *seat = gdk_display_get_default_seat (display);
+
+      gdk_seat_grab (seat,
+                     GDK_SURFACE (self),
+                     GDK_SEAT_CAPABILITY_ALL,
+                     TRUE,
+                     NULL, NULL,
+                     show_grabbing_popup,
+                     NULL);
+    }
+  else
+    {
+      show_popup (GDK_MACOS_POPUP_SURFACE (self));
+    }
+
+  return GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self));
+}
+
+static GdkGravity
+gdk_macos_popup_surface_get_surface_anchor (GdkPopup *popup)
+{
+  return GDK_SURFACE (popup)->popup.surface_anchor;
+}
+
+static GdkGravity
+gdk_macos_popup_surface_get_rect_anchor (GdkPopup *popup)
+{
+  return GDK_SURFACE (popup)->popup.rect_anchor;
+}
+
+static int
+gdk_macos_popup_surface_get_position_x (GdkPopup *popup)
+{
+  return GDK_SURFACE (popup)->x;
+}
+
+static int
+gdk_macos_popup_surface_get_position_y (GdkPopup *popup)
+{
+  return GDK_SURFACE (popup)->y;
+}
+
+static void
+popup_interface_init (GdkPopupInterface *iface)
+{
+  iface->present = gdk_macos_popup_surface_present;
+  iface->get_surface_anchor = gdk_macos_popup_surface_get_surface_anchor;
+  iface->get_rect_anchor = gdk_macos_popup_surface_get_rect_anchor;
+  iface->get_position_x = gdk_macos_popup_surface_get_position_x;
+  iface->get_position_y = gdk_macos_popup_surface_get_position_y;
+}
+
+G_DEFINE_TYPE_WITH_CODE (GdkMacosPopupSurface, _gdk_macos_popup_surface, GDK_TYPE_MACOS_SURFACE,
+                         G_IMPLEMENT_INTERFACE (GDK_TYPE_POPUP, popup_interface_init))
+
+enum {
+  PROP_0,
+  LAST_PROP,
+};
+
+static void
+_gdk_macos_popup_surface_finalize (GObject *object)
+{
+  GdkMacosPopupSurface *self = (GdkMacosPopupSurface *)object;
+
+  g_clear_object (&GDK_SURFACE (self)->parent);
+  g_clear_pointer (&self->layout, gdk_popup_layout_unref);
+
+  G_OBJECT_CLASS (_gdk_macos_popup_surface_parent_class)->finalize (object);
+}
+
+static void
+_gdk_macos_popup_surface_get_property (GObject    *object,
+                                       guint       prop_id,
+                                       GValue     *value,
+                                       GParamSpec *pspec)
+{
+  GdkSurface *surface = GDK_SURFACE (object);
+
+  switch (prop_id)
+    {
+    case LAST_PROP + GDK_POPUP_PROP_PARENT:
+      g_value_set_object (value, surface->parent);
+      break;
+
+    case LAST_PROP + GDK_POPUP_PROP_AUTOHIDE:
+      g_value_set_boolean (value, surface->autohide);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+_gdk_macos_popup_surface_set_property (GObject      *object,
+                                       guint         prop_id,
+                                       const GValue *value,
+                                       GParamSpec   *pspec)
+{
+  GdkSurface *surface = GDK_SURFACE (object);
+
+  switch (prop_id)
+    {
+    case LAST_PROP + GDK_POPUP_PROP_PARENT:
+      surface->parent = g_value_dup_object (value);
+      if (surface->parent)
+        surface->parent->children = g_list_prepend (surface->parent->children, surface);
+      break;
+
+    case LAST_PROP + GDK_POPUP_PROP_AUTOHIDE:
+      surface->autohide = g_value_get_boolean (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+_gdk_macos_popup_surface_class_init (GdkMacosPopupSurfaceClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = _gdk_macos_popup_surface_finalize;
+  object_class->get_property = _gdk_macos_popup_surface_get_property;
+  object_class->set_property = _gdk_macos_popup_surface_set_property;
+
+  gdk_popup_install_properties (object_class, 1);
+}
+
+static void
+_gdk_macos_popup_surface_init (GdkMacosPopupSurface *self)
+{
+}
+
+GdkMacosSurface *
+_gdk_macos_popup_surface_new (GdkMacosDisplay *display,
+                              GdkSurface      *parent,
+                              GdkFrameClock   *frame_clock,
+                              int              x,
+                              int              y,
+                              int              width,
+                              int              height)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  GdkMacosWindow *window;
+  GdkMacosSurface *self;
+  NSScreen *screen;
+  NSUInteger style_mask;
+  NSRect content_rect;
+  NSRect screen_rect;
+  int nx;
+  int ny;
+
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
+  g_return_val_if_fail (!frame_clock || GDK_IS_FRAME_CLOCK (frame_clock), NULL);
+  g_return_val_if_fail (!parent || GDK_IS_MACOS_SURFACE (parent), NULL);
+
+  style_mask = NSWindowStyleMaskBorderless;
+
+  _gdk_macos_display_to_display_coords (display, x, y, &nx, &ny);
+
+  screen = _gdk_macos_display_get_screen_at_display_coords (display, nx, ny);
+  screen_rect = [screen frame];
+  nx -= screen_rect.origin.x;
+  ny -= screen_rect.origin.y;
+  content_rect = NSMakeRect (nx, ny - height, width, height);
+
+  window = [[GdkMacosWindow alloc] initWithContentRect:content_rect
+                                             styleMask:style_mask
+                                               backing:NSBackingStoreBuffered
+                                                 defer:NO
+                                                screen:screen];
+
+  [window setOpaque:NO];
+  [window setBackgroundColor:[NSColor clearColor]];
+  [window setDecorated:NO];
+
+#if 0
+  /* NOTE: We could set these to be popup level, but then
+   * [NSApp orderedWindows] would not give us the windows
+   * back with the stacking order applied.
+   */
+  [window setLevel:NSPopUpMenuWindowLevel];
+#endif
+
+  self = g_object_new (GDK_TYPE_MACOS_POPUP_SURFACE,
+                       "display", display,
+                       "frame-clock", frame_clock,
+                       "native", window,
+                       "parent", parent,
+                       NULL);
+
+  GDK_END_MACOS_ALLOC_POOL;
+
+  return g_steal_pointer (&self);
+}
+
+void
+_gdk_macos_popup_surface_attach_to_parent (GdkMacosPopupSurface *self)
+{
+  GdkSurface *surface = (GdkSurface *)self;
+
+  g_return_if_fail (GDK_IS_MACOS_POPUP_SURFACE (self));
+
+  if (GDK_SURFACE_DESTROYED (surface))
+    return;
+
+  if (surface->parent != NULL && !GDK_SURFACE_DESTROYED (surface->parent))
+    {
+      NSWindow *parent = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface->parent));
+      NSWindow *window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
+
+      [parent addChildWindow:window ordered:NSWindowAbove];
+
+      _gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (surface->display));
+    }
+}
+
+void
+_gdk_macos_popup_surface_detach_from_parent (GdkMacosPopupSurface *self)
+{
+  GdkSurface *surface = (GdkSurface *)self;
+
+  g_return_if_fail (GDK_IS_MACOS_POPUP_SURFACE (self));
+
+  if (GDK_SURFACE_DESTROYED (surface))
+    return;
+
+  if (surface->parent != NULL && !GDK_SURFACE_DESTROYED (surface->parent))
+    {
+      NSWindow *parent = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface->parent));
+      NSWindow *window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
+
+      [parent removeChildWindow:window];
+
+      _gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (surface->display));
+    }
+}
+
+void
+_gdk_macos_popup_surface_reposition (GdkMacosPopupSurface *self)
+{
+  g_return_if_fail (GDK_IS_MACOS_POPUP_SURFACE (self));
+
+  if (self->layout == NULL ||
+      !gdk_surface_get_mapped (GDK_SURFACE (self)) ||
+      GDK_SURFACE (self)->parent == NULL)
+    return;
+
+  gdk_macos_popup_surface_layout (self,
+                                  GDK_SURFACE (self)->width,
+                                  GDK_SURFACE (self)->height,
+                                  self->layout);
+}
diff --git a/gdk/macos/gdkmacosseat-private.h b/gdk/macos/gdkmacosseat-private.h
new file mode 100644 (file)
index 0000000..57e5605
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_SEAT_PRIVATE_H__
+#define __GDK_MACOS_SEAT_PRIVATE_H__
+
+#include <AppKit/AppKit.h>
+
+#include "gdkmacosdisplay.h"
+
+#include "gdkseatprivate.h"
+
+G_BEGIN_DECLS
+
+GdkSeat *_gdk_macos_seat_new (GdkMacosDisplay *display);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_SEAT_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacosseat.c b/gdk/macos/gdkmacosseat.c
new file mode 100644 (file)
index 0000000..cb3c374
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include <gdk/gdk.h>
+
+#include "gdkdeviceprivate.h"
+#include "gdkseatdefaultprivate.h"
+
+#include "gdkmacosdevice.h"
+#include "gdkmacosseat-private.h"
+
+GdkSeat *
+_gdk_macos_seat_new (GdkMacosDisplay *display)
+{
+  GdkDevice *core_keyboard;
+  GdkDevice *core_pointer;
+  GdkSeat *seat;
+
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
+
+  core_pointer = g_object_new (GDK_TYPE_MACOS_DEVICE,
+                               "name", "Core Pointer",
+                               "type", GDK_DEVICE_TYPE_LOGICAL,
+                               "source", GDK_SOURCE_MOUSE,
+                               "has-cursor", TRUE,
+                               "display", display,
+                               NULL);
+  core_keyboard = g_object_new (GDK_TYPE_MACOS_DEVICE,
+                                "name", "Core Keyboard",
+                                "type", GDK_DEVICE_TYPE_LOGICAL,
+                                "source", GDK_SOURCE_KEYBOARD,
+                                "has-cursor", FALSE,
+                                "display", display,
+                                NULL);
+
+  _gdk_device_set_associated_device (GDK_DEVICE (core_pointer),
+                                     GDK_DEVICE (core_keyboard));
+  _gdk_device_set_associated_device (GDK_DEVICE (core_keyboard),
+                                     GDK_DEVICE (core_pointer));
+
+  seat = gdk_seat_default_new_for_logical_pair (core_pointer, core_keyboard);
+
+  g_object_unref (core_pointer);
+  g_object_unref (core_keyboard);
+
+  return g_steal_pointer (&seat);
+}
diff --git a/gdk/macos/gdkmacossurface-private.h b/gdk/macos/gdkmacossurface-private.h
new file mode 100644 (file)
index 0000000..f5a52db
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_SURFACE_PRIVATE_H__
+#define __GDK_MACOS_SURFACE_PRIVATE_H__
+
+#include <AppKit/AppKit.h>
+#include <cairo.h>
+
+#include "gdkinternals.h"
+#include "gdksurfaceprivate.h"
+
+#include "gdkmacosdisplay.h"
+#include "gdkmacossurface.h"
+
+#import "GdkMacosWindow.h"
+
+G_BEGIN_DECLS
+
+#define GDK_MACOS_SURFACE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_MACOS_SURFACE, GdkMacosSurfaceClass))
+#define GDK_IS_MACOS_SURFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_MACOS_SURFACE))
+#define GDK_MACOS_SURFACE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_MACOS_SURFACE, GdkMacosSurfaceClass))
+
+struct _GdkMacosSurface
+{
+  GdkSurface parent_instance;
+
+  GList main;
+  GList sorted;
+  GList frame;
+
+  GdkMacosWindow *window;
+  GPtrArray *monitors;
+  cairo_region_t *input_region;
+  char *title;
+
+  int root_x;
+  int root_y;
+
+  int shadow_top;
+  int shadow_right;
+  int shadow_bottom;
+  int shadow_left;
+
+  gint64 pending_frame_counter;
+
+  guint did_initial_present : 1;
+};
+
+struct _GdkMacosSurfaceClass
+{
+  GdkSurfaceClass parent_class;
+};
+
+GdkMacosSurface   *_gdk_macos_surface_new                     (GdkMacosDisplay    *display,
+                                                               GdkSurfaceType      surface_type,
+                                                               GdkSurface         *parent,
+                                                               int                 x,
+                                                               int                 y,
+                                                               int                 width,
+                                                               int                 height);
+NSWindow          *_gdk_macos_surface_get_native              (GdkMacosSurface    *self);
+CGDirectDisplayID  _gdk_macos_surface_get_screen_id           (GdkMacosSurface    *self);
+const char        *_gdk_macos_surface_get_title               (GdkMacosSurface    *self);
+void               _gdk_macos_surface_set_title               (GdkMacosSurface    *self,
+                                                               const gchar        *title);
+void               _gdk_macos_surface_get_shadow              (GdkMacosSurface    *self,
+                                                               gint               *top,
+                                                               gint               *right,
+                                                               gint               *bottom,
+                                                               gint               *left);
+NSView            *_gdk_macos_surface_get_view                (GdkMacosSurface    *self);
+gboolean           _gdk_macos_surface_get_modal_hint          (GdkMacosSurface    *self);
+void               _gdk_macos_surface_set_modal_hint          (GdkMacosSurface    *self,
+                                                               gboolean            modal_hint);
+void               _gdk_macos_surface_set_geometry_hints      (GdkMacosSurface    *self,
+                                                               const GdkGeometry  *geometry,
+                                                               GdkSurfaceHints     geom_mask);
+void               _gdk_macos_surface_resize                  (GdkMacosSurface    *self,
+                                                               int                 width,
+                                                               int                 height);
+void               _gdk_macos_surface_update_fullscreen_state (GdkMacosSurface    *self);
+void               _gdk_macos_surface_update_position         (GdkMacosSurface    *self);
+void               _gdk_macos_surface_show                    (GdkMacosSurface    *self);
+void               _gdk_macos_surface_thaw                    (GdkMacosSurface    *self,
+                                                               gint64              predicted_presentation_time,
+                                                               gint64              refresh_interval);
+CGContextRef       _gdk_macos_surface_acquire_context         (GdkMacosSurface    *self,
+                                                               gboolean            clear_scale,
+                                                               gboolean            antialias);
+void               _gdk_macos_surface_release_context         (GdkMacosSurface    *self,
+                                                               CGContextRef        cg_context);
+void               _gdk_macos_surface_synthesize_null_key     (GdkMacosSurface    *self);
+void               _gdk_macos_surface_move                    (GdkMacosSurface    *self,
+                                                               int                 x,
+                                                               int                 y);
+void               _gdk_macos_surface_move_resize             (GdkMacosSurface    *self,
+                                                               int                 x,
+                                                               int                 y,
+                                                               int                 width,
+                                                               int                 height);
+gboolean           _gdk_macos_surface_is_tracking             (GdkMacosSurface    *self,
+                                                               NSTrackingArea     *area);
+void               _gdk_macos_surface_monitor_changed         (GdkMacosSurface    *self);
+GdkMonitor        *_gdk_macos_surface_get_best_monitor        (GdkMacosSurface    *self);
+void               _gdk_macos_surface_reposition_children     (GdkMacosSurface    *self);
+void               _gdk_macos_surface_set_opacity             (GdkMacosSurface    *self,
+                                                               double              opacity);
+void               _gdk_macos_surface_get_root_coords         (GdkMacosSurface    *self,
+                                                               int                *x,
+                                                               int                *y);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_SURFACE_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacossurface.c b/gdk/macos/gdkmacossurface.c
new file mode 100644 (file)
index 0000000..83fad33
--- /dev/null
@@ -0,0 +1,1071 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include <AppKit/AppKit.h>
+#include <float.h>
+#include <gdk/gdk.h>
+
+#import "GdkMacosCairoView.h"
+
+#include "gdkdeviceprivate.h"
+#include "gdkdisplay.h"
+#include "gdkframeclockidleprivate.h"
+#include "gdkinternals.h"
+#include "gdksurfaceprivate.h"
+
+#include "gdkmacosdevice.h"
+#include "gdkmacosdisplay-private.h"
+#include "gdkmacosdrag-private.h"
+#include "gdkmacosdragsurface-private.h"
+#include "gdkmacosglcontext-private.h"
+#include "gdkmacosmonitor-private.h"
+#include "gdkmacospopupsurface-private.h"
+#include "gdkmacossurface-private.h"
+#include "gdkmacostoplevelsurface-private.h"
+#include "gdkmacosutils-private.h"
+
+G_DEFINE_ABSTRACT_TYPE (GdkMacosSurface, gdk_macos_surface, GDK_TYPE_SURFACE)
+
+enum {
+  PROP_0,
+  PROP_NATIVE,
+  LAST_PROP
+};
+
+static GParamSpec *properties [LAST_PROP];
+
+static gboolean
+window_is_fullscreen (GdkMacosSurface *self)
+{
+  g_assert (GDK_IS_MACOS_SURFACE (self));
+
+  return ([self->window styleMask] & NSWindowStyleMaskFullScreen) != 0;
+}
+
+void
+_gdk_macos_surface_reposition_children (GdkMacosSurface *self)
+{
+  g_assert (GDK_IS_MACOS_SURFACE (self));
+
+  if (GDK_SURFACE_DESTROYED (self))
+    return;
+
+  if (!gdk_surface_get_mapped (GDK_SURFACE (self)))
+    return;
+
+  for (const GList *iter = GDK_SURFACE (self)->children;
+       iter != NULL;
+       iter = iter->next)
+    {
+      GdkMacosSurface *child = iter->data;
+
+      g_assert (GDK_IS_MACOS_SURFACE (child));
+
+      if (GDK_IS_MACOS_POPUP_SURFACE (child))
+        _gdk_macos_popup_surface_reposition (GDK_MACOS_POPUP_SURFACE (child));
+    }
+
+  if (GDK_IS_POPUP (self) || self->did_initial_present)
+    g_signal_emit_by_name (self, "popup-layout-changed");
+}
+
+static void
+gdk_macos_surface_set_input_region (GdkSurface     *surface,
+                                    cairo_region_t *region)
+{
+}
+
+static void
+gdk_macos_surface_set_opaque_region (GdkSurface     *surface,
+                                     cairo_region_t *region)
+{
+  NSView *nsview;
+
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+
+  if ((nsview = _gdk_macos_surface_get_view (GDK_MACOS_SURFACE (surface))) &&
+      GDK_IS_MACOS_CAIRO_VIEW (nsview))
+    [(GdkMacosCairoView *)nsview setOpaqueRegion:region];
+}
+
+static void
+gdk_macos_surface_hide (GdkSurface *surface)
+{
+  GdkMacosSurface *self = (GdkMacosSurface *)surface;
+  GdkSeat *seat;
+
+  g_assert (GDK_IS_MACOS_SURFACE (self));
+
+  seat = gdk_display_get_default_seat (surface->display);
+  gdk_seat_ungrab (seat);
+
+  [self->window hide];
+
+  _gdk_surface_clear_update_area (surface);
+}
+
+static gint
+gdk_macos_surface_get_scale_factor (GdkSurface *surface)
+{
+  GdkMacosSurface *self = (GdkMacosSurface *)surface;
+
+  g_assert (GDK_IS_MACOS_SURFACE (self));
+
+  return [self->window backingScaleFactor];
+}
+
+static void
+gdk_macos_surface_set_shadow_width (GdkSurface *surface,
+                                    int         left,
+                                    int         right,
+                                    int         top,
+                                    int         bottom)
+{
+  GdkMacosSurface *self = (GdkMacosSurface *)surface;
+
+  g_assert (GDK_IS_MACOS_SURFACE (self));
+
+  self->shadow_top = top;
+  self->shadow_right = right;
+  self->shadow_bottom = bottom;
+  self->shadow_left = left;
+
+  if (top || right || bottom || left)
+    [self->window setHasShadow:NO];
+}
+
+static void
+gdk_macos_surface_begin_frame (GdkMacosSurface *self)
+{
+  g_assert (GDK_IS_MACOS_SURFACE (self));
+
+}
+
+static void
+gdk_macos_surface_end_frame (GdkMacosSurface *self)
+{
+  GdkFrameTimings *timings;
+  GdkFrameClock *frame_clock;
+  GdkDisplay *display;
+
+  g_assert (GDK_IS_MACOS_SURFACE (self));
+
+  display = gdk_surface_get_display (GDK_SURFACE (self));
+  frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self));
+
+  if ((timings = gdk_frame_clock_get_current_timings (frame_clock)))
+    self->pending_frame_counter = timings->frame_counter;
+
+  _gdk_macos_display_add_frame_callback (GDK_MACOS_DISPLAY (display), self);
+
+  gdk_surface_freeze_updates (GDK_SURFACE (self));
+}
+
+static void
+gdk_macos_surface_before_paint (GdkMacosSurface *self,
+                                GdkFrameClock   *frame_clock)
+{
+  GdkSurface *surface = (GdkSurface *)self;
+
+  g_assert (GDK_IS_MACOS_SURFACE (self));
+  g_assert (GDK_IS_FRAME_CLOCK (frame_clock));
+
+  if (surface->update_freeze_count > 0)
+    return;
+
+  gdk_macos_surface_begin_frame (self);
+}
+
+static void
+gdk_macos_surface_after_paint (GdkMacosSurface *self,
+                               GdkFrameClock   *frame_clock)
+{
+  GdkSurface *surface = (GdkSurface *)self;
+
+  g_assert (GDK_IS_MACOS_SURFACE (self));
+  g_assert (GDK_IS_FRAME_CLOCK (frame_clock));
+
+  if (surface->update_freeze_count > 0)
+    return;
+
+  gdk_macos_surface_end_frame (self);
+}
+
+static void
+gdk_macos_surface_get_root_coords (GdkSurface *surface,
+                                   int         x,
+                                   int         y,
+                                   int        *root_x,
+                                   int        *root_y)
+{
+  GdkMacosSurface *self = (GdkMacosSurface *)surface;
+
+  g_assert (GDK_IS_MACOS_SURFACE (self));
+
+  if (root_x)
+    *root_x = self->root_x + x;
+
+  if (root_y)
+    *root_y = self->root_y + y;
+}
+
+static gboolean
+gdk_macos_surface_get_device_state (GdkSurface      *surface,
+                                    GdkDevice       *device,
+                                    gdouble         *x,
+                                    gdouble         *y,
+                                    GdkModifierType *mask)
+{
+  GdkDisplay *display;
+  NSWindow *nswindow;
+  NSPoint point;
+  int x_tmp;
+  int y_tmp;
+
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+  g_assert (GDK_IS_MACOS_DEVICE (device));
+  g_assert (x != NULL);
+  g_assert (y != NULL);
+  g_assert (mask != NULL);
+
+  display = gdk_surface_get_display (surface);
+  nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface));
+  point = [nswindow mouseLocationOutsideOfEventStream];
+
+  _gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (display),
+                                          point.x, point.y,
+                                          &x_tmp, &y_tmp);
+
+  *x = x_tmp;
+  *y = x_tmp;
+
+  return TRUE;
+}
+
+static void
+gdk_macos_surface_get_geometry (GdkSurface *surface,
+                                int        *x,
+                                int        *y,
+                                int        *width,
+                                int        *height)
+{
+  g_assert (GDK_IS_MACOS_SURFACE (surface));
+
+  if (x != NULL)
+    *x = surface->x;
+
+  if (y != NULL)
+    *y = surface->y;
+
+  if (width != NULL)
+    *width = surface->width;
+
+  if (height != NULL)
+    *height = surface->height;
+}
+
+static GdkDrag *
+gdk_macos_surface_drag_begin (GdkSurface         *surface,
+                              GdkDevice          *device,
+                              GdkContentProvider *content,
+                              GdkDragAction       actions,
+                              double              dx,
+                              double              dy)
+{
+  GdkMacosSurface *self = (GdkMacosSurface *)surface;
+  GdkMacosSurface *drag_surface;
+  GdkMacosDrag *drag;
+  GdkCursor *cursor;
+  GdkSeat *seat;
+  double px;
+  double py;
+  int sx;
+  int sy;
+
+  g_assert (GDK_IS_MACOS_SURFACE (self));
+  g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self) ||
+            GDK_IS_MACOS_POPUP_SURFACE (self));
+  g_assert (GDK_IS_MACOS_DEVICE (device));
+  g_assert (GDK_IS_CONTENT_PROVIDER (content));
+
+  seat = gdk_device_get_seat (device);
+  _gdk_device_query_state (device, surface, NULL, &px, &py, NULL);
+  _gdk_macos_surface_get_root_coords (GDK_MACOS_SURFACE (surface), &sx, &sy);
+  drag_surface = _gdk_macos_surface_new (GDK_MACOS_DISPLAY (surface->display),
+                                         GDK_SURFACE_TEMP,
+                                         surface,
+                                         -99, -99, 1, 1);
+  drag = g_object_new (GDK_TYPE_MACOS_DRAG,
+                       "drag-surface", drag_surface,
+                       "surface", surface,
+                       "device", device,
+                       "content", content,
+                       "actions", actions,
+                       NULL);
+  g_clear_object (&drag_surface);
+
+  cursor = gdk_drag_get_cursor (GDK_DRAG (drag),
+                                gdk_drag_get_selected_action (GDK_DRAG (drag)));
+  gdk_drag_set_cursor (GDK_DRAG (drag), cursor);
+
+  if (!_gdk_macos_drag_begin (drag))
+    {
+      g_object_unref (drag);
+      return NULL;
+    }
+
+  /* Hold a reference until drop_done is called */
+  g_object_ref (drag);
+
+  return GDK_DRAG (g_steal_pointer (&drag));
+}
+
+static GdkGLContext *
+gdk_macos_surface_create_gl_context (GdkSurface    *surface,
+                                     gboolean       attached,
+                                     GdkGLContext  *share,
+                                     GError       **error)
+{
+  GdkMacosSurface *self = (GdkMacosSurface *)surface;
+
+  g_assert (GDK_IS_MACOS_SURFACE (self));
+  g_assert (!share || GDK_IS_GL_CONTEXT (share));
+
+  return _gdk_macos_gl_context_new (self, attached, share, error);
+}
+
+static void
+gdk_macos_surface_destroy (GdkSurface *surface,
+                           gboolean    foreign_destroy)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  GdkMacosSurface *self = (GdkMacosSurface *)surface;
+  GdkMacosWindow *window = g_steal_pointer (&self->window);
+
+  g_clear_pointer (&self->title, g_free);
+
+  if (window != NULL)
+    [window close];
+
+  _gdk_macos_display_surface_removed (GDK_MACOS_DISPLAY (surface->display), self);
+
+  g_clear_pointer (&self->monitors, g_ptr_array_unref);
+
+  g_assert (self->sorted.prev == NULL);
+  g_assert (self->sorted.next == NULL);
+  g_assert (self->frame.prev == NULL);
+  g_assert (self->frame.next == NULL);
+  g_assert (self->main.prev == NULL);
+  g_assert (self->main.next == NULL);
+
+  GDK_END_MACOS_ALLOC_POOL;
+}
+
+static void
+gdk_macos_surface_constructed (GObject *object)
+{
+  GdkMacosSurface *self = (GdkMacosSurface *)object;
+  GdkFrameClock *frame_clock;
+
+  g_assert (GDK_IS_MACOS_SURFACE (self));
+
+  G_OBJECT_CLASS (gdk_macos_surface_parent_class)->constructed (object);
+
+  if (self->window != NULL)
+    {
+      NSRect bounds = [[self->window contentView] bounds];
+
+      GDK_SURFACE (self)->width = bounds.size.width;
+      GDK_SURFACE (self)->height = bounds.size.height;
+      _gdk_macos_surface_update_position (self);
+    }
+
+  if ((frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self))))
+    {
+      g_signal_connect_object (frame_clock,
+                               "before-paint",
+                               G_CALLBACK (gdk_macos_surface_before_paint),
+                               self,
+                               G_CONNECT_SWAPPED);
+      g_signal_connect_object (frame_clock,
+                               "after-paint",
+                               G_CALLBACK (gdk_macos_surface_after_paint),
+                               self,
+                               G_CONNECT_SWAPPED);
+    }
+}
+
+static void
+gdk_macos_surface_get_property (GObject    *object,
+                                guint       prop_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+  GdkMacosSurface *self = GDK_MACOS_SURFACE (object);
+
+  switch (prop_id)
+    {
+    case PROP_NATIVE:
+      g_value_set_pointer (value, self->window);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gdk_macos_surface_set_property (GObject      *object,
+                                guint         prop_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+  GdkMacosSurface *self = GDK_MACOS_SURFACE (object);
+
+  switch (prop_id)
+    {
+    case PROP_NATIVE:
+      self->window = g_value_get_pointer (value);
+      [self->window setGdkSurface:self];
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gdk_macos_surface_class_init (GdkMacosSurfaceClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkSurfaceClass *surface_class = GDK_SURFACE_CLASS (klass);
+
+  object_class->constructed = gdk_macos_surface_constructed;
+  object_class->get_property = gdk_macos_surface_get_property;
+  object_class->set_property = gdk_macos_surface_set_property;
+
+  surface_class->create_gl_context = gdk_macos_surface_create_gl_context;
+  surface_class->destroy = gdk_macos_surface_destroy;
+  surface_class->drag_begin = gdk_macos_surface_drag_begin;
+  surface_class->get_device_state = gdk_macos_surface_get_device_state;
+  surface_class->get_geometry = gdk_macos_surface_get_geometry;
+  surface_class->get_root_coords = gdk_macos_surface_get_root_coords;
+  surface_class->get_scale_factor = gdk_macos_surface_get_scale_factor;
+  surface_class->hide = gdk_macos_surface_hide;
+  surface_class->set_input_region = gdk_macos_surface_set_input_region;
+  surface_class->set_opaque_region = gdk_macos_surface_set_opaque_region;
+  surface_class->set_shadow_width = gdk_macos_surface_set_shadow_width;
+
+  properties [PROP_NATIVE] =
+    g_param_spec_pointer ("native",
+                          "Native",
+                          "The native NSWindow",
+                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, LAST_PROP, properties);
+}
+
+static void
+gdk_macos_surface_init (GdkMacosSurface *self)
+{
+  self->frame.data = self;
+  self->main.data = self;
+  self->sorted.data = self;
+  self->monitors = g_ptr_array_new_with_free_func (g_object_unref);
+}
+
+GdkMacosSurface *
+_gdk_macos_surface_new (GdkMacosDisplay   *display,
+                        GdkSurfaceType     surface_type,
+                        GdkSurface        *parent,
+                        int                x,
+                        int                y,
+                        int                width,
+                        int                height)
+{
+  GdkFrameClock *frame_clock;
+  GdkMacosSurface *ret;
+
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
+
+  if (parent != NULL)
+    frame_clock = g_object_ref (gdk_surface_get_frame_clock (parent));
+  else
+    frame_clock = _gdk_frame_clock_idle_new ();
+
+  switch (surface_type)
+    {
+    case GDK_SURFACE_TOPLEVEL:
+      ret = _gdk_macos_toplevel_surface_new (display, parent, frame_clock, x, y, width, height);
+      break;
+
+    case GDK_SURFACE_POPUP:
+      ret = _gdk_macos_popup_surface_new (display, parent, frame_clock, x, y, width, height);
+      break;
+
+    case GDK_SURFACE_TEMP:
+      ret = _gdk_macos_drag_surface_new (display, frame_clock, x, y, width, height);
+      break;
+
+    default:
+      g_warn_if_reached ();
+      ret = NULL;
+    }
+
+  if (ret != NULL)
+    _gdk_macos_surface_monitor_changed (ret);
+
+  g_object_unref (frame_clock);
+
+  return g_steal_pointer (&ret);
+}
+
+void
+_gdk_macos_surface_get_shadow (GdkMacosSurface *self,
+                               gint            *top,
+                               gint            *right,
+                               gint            *bottom,
+                               gint            *left)
+{
+
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+
+  if (top)
+    *top = self->shadow_top;
+
+  if (left)
+    *left = self->shadow_left;
+
+  if (bottom)
+    *bottom = self->shadow_bottom;
+
+  if (right)
+    *right = self->shadow_right;
+}
+
+const char *
+_gdk_macos_surface_get_title (GdkMacosSurface *self)
+{
+
+  return self->title;
+}
+
+void
+_gdk_macos_surface_set_title (GdkMacosSurface *self,
+                              const gchar     *title)
+{
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+
+  if (title == NULL)
+    title = "";
+
+  if (g_strcmp0 (self->title, title) != 0)
+    {
+      g_free (self->title);
+      self->title = g_strdup (title);
+
+      GDK_BEGIN_MACOS_ALLOC_POOL;
+      [self->window setTitle:[NSString stringWithUTF8String:title]];
+      GDK_END_MACOS_ALLOC_POOL;
+    }
+}
+
+CGDirectDisplayID
+_gdk_macos_surface_get_screen_id (GdkMacosSurface *self)
+{
+  g_return_val_if_fail (GDK_IS_MACOS_SURFACE (self), (CGDirectDisplayID)-1);
+
+  if (self->window != NULL)
+    {
+      NSScreen *screen = [self->window screen];
+      return [[[screen deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
+    }
+
+  return (CGDirectDisplayID)-1;
+}
+
+NSWindow *
+_gdk_macos_surface_get_native (GdkMacosSurface *self)
+{
+  g_return_val_if_fail (GDK_IS_MACOS_SURFACE (self), NULL);
+
+  return (NSWindow *)self->window;
+}
+
+void
+_gdk_macos_surface_set_geometry_hints (GdkMacosSurface   *self,
+                                       const GdkGeometry *geometry,
+                                       GdkSurfaceHints    geom_mask)
+{
+  NSSize max_size;
+  NSSize min_size;
+
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+  g_return_if_fail (geometry != NULL);
+  g_return_if_fail (self->window != NULL);
+
+  if (geom_mask & GDK_HINT_POS) { /* TODO */ }
+  if (geom_mask & GDK_HINT_USER_POS) { /* TODO */ }
+  if (geom_mask & GDK_HINT_USER_SIZE) { /* TODO */ }
+
+  if (geom_mask & GDK_HINT_MAX_SIZE)
+    max_size = NSMakeSize (geometry->max_width, geometry->max_height);
+  else
+    max_size = NSMakeSize (FLT_MAX, FLT_MAX);
+  [self->window setContentMaxSize:max_size];
+
+  if (geom_mask & GDK_HINT_MIN_SIZE)
+    min_size = NSMakeSize (geometry->min_width, geometry->min_height);
+  else
+    min_size = NSMakeSize (1, 1);
+  [self->window setContentMinSize:min_size];
+
+  if (geom_mask & GDK_HINT_BASE_SIZE) { /* TODO */ }
+
+  if (geom_mask & GDK_HINT_RESIZE_INC)
+    {
+      NSSize size = NSMakeSize (geometry->width_inc, geometry->height_inc);
+      [self->window setContentResizeIncrements:size];
+    }
+
+  if (geom_mask & GDK_HINT_ASPECT)
+    {
+      NSSize size;
+
+      if (geometry->min_aspect != geometry->max_aspect)
+        g_warning ("Only equal minimum and maximum aspect ratios are supported on Mac OS. Using minimum aspect ratio...");
+
+      size.width = geometry->min_aspect;
+      size.height = 1.0;
+
+      [self->window setContentAspectRatio:size];
+    }
+
+  if (geom_mask & GDK_HINT_WIN_GRAVITY) { /* TODO */ }
+}
+
+void
+_gdk_macos_surface_resize (GdkMacosSurface *self,
+                           int              width,
+                           int              height)
+{
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+
+  _gdk_macos_surface_move_resize (self, -1, -1, width, height);
+}
+
+void
+_gdk_macos_surface_update_fullscreen_state (GdkMacosSurface *self)
+{
+  GdkSurfaceState state;
+  gboolean is_fullscreen;
+  gboolean was_fullscreen;
+
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+
+  state = GDK_SURFACE (self)->state;
+  is_fullscreen = window_is_fullscreen (self);
+  was_fullscreen = (state & GDK_SURFACE_STATE_FULLSCREEN) != 0;
+
+  if (is_fullscreen != was_fullscreen)
+    {
+      if (is_fullscreen)
+        gdk_synthesize_surface_state (GDK_SURFACE (self), 0, GDK_SURFACE_STATE_FULLSCREEN);
+      else
+        gdk_synthesize_surface_state (GDK_SURFACE (self), GDK_SURFACE_STATE_FULLSCREEN, 0);
+    }
+}
+
+void
+_gdk_macos_surface_update_position (GdkMacosSurface *self)
+{
+  GdkSurface *surface = GDK_SURFACE (self);
+  GdkDisplay *display = gdk_surface_get_display (surface);
+  NSRect frame_rect = [self->window frame];
+  NSRect content_rect = [self->window contentRectForFrameRect:frame_rect];
+
+  _gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (display),
+                                          content_rect.origin.x,
+                                          content_rect.origin.y + content_rect.size.height,
+                                          &self->root_x, &self->root_y);
+
+  if (surface->parent != NULL)
+    {
+      surface->x = self->root_x - GDK_MACOS_SURFACE (surface->parent)->root_x;
+      surface->y = self->root_y - GDK_MACOS_SURFACE (surface->parent)->root_y;
+    }
+  else
+    {
+      surface->x = self->root_x;
+      surface->y = self->root_y;
+    }
+}
+
+void
+_gdk_macos_surface_thaw (GdkMacosSurface *self,
+                         gint64           presentation_time,
+                         gint64           refresh_interval)
+{
+  GdkFrameTimings *timings;
+  GdkFrameClock *frame_clock;
+
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+
+  gdk_surface_thaw_updates (GDK_SURFACE (self));
+
+  frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self));
+
+  if (self->pending_frame_counter)
+    {
+      timings = gdk_frame_clock_get_timings (frame_clock, self->pending_frame_counter);
+
+      if (timings != NULL)
+        timings->presentation_time = presentation_time - refresh_interval;
+
+      self->pending_frame_counter = 0;
+    }
+
+  timings = gdk_frame_clock_get_current_timings (frame_clock);
+
+  if (timings != NULL)
+    {
+      timings->refresh_interval = refresh_interval;
+      timings->predicted_presentation_time = presentation_time;
+    }
+}
+
+void
+_gdk_macos_surface_show (GdkMacosSurface *self)
+{
+  gboolean was_mapped;
+
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+
+  if (GDK_SURFACE_DESTROYED (self))
+    return;
+
+  was_mapped = GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self));
+
+  if (!was_mapped)
+    gdk_synthesize_surface_state (GDK_SURFACE (self), GDK_SURFACE_STATE_WITHDRAWN, 0);
+
+  _gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (GDK_SURFACE (self)->display));
+
+  [self->window showAndMakeKey:YES];
+
+  if (!was_mapped)
+    {
+      if (gdk_surface_get_mapped (GDK_SURFACE (self)))
+        {
+          _gdk_macos_surface_update_position (self);
+          gdk_surface_invalidate_rect (GDK_SURFACE (self), NULL);
+        }
+    }
+
+  [[self->window contentView] setNeedsDisplay:YES];
+}
+
+CGContextRef
+_gdk_macos_surface_acquire_context (GdkMacosSurface *self,
+                                    gboolean         clear_scale,
+                                    gboolean         antialias)
+{
+  CGContextRef cg_context;
+
+  g_return_val_if_fail (GDK_IS_MACOS_SURFACE (self), NULL);
+
+  if (GDK_SURFACE_DESTROYED (self))
+    return NULL;
+
+  if (!(cg_context = [[NSGraphicsContext currentContext] CGContext]))
+    return NULL;
+
+  CGContextSaveGState (cg_context);
+
+  if (!antialias)
+    CGContextSetAllowsAntialiasing (cg_context, antialias);
+
+  if (clear_scale)
+    {
+      CGSize scale;
+
+      scale = CGSizeMake (1.0, 1.0);
+      scale = CGContextConvertSizeToDeviceSpace (cg_context, scale);
+
+      CGContextScaleCTM (cg_context, 1.0 / scale.width, 1.0 / scale.height);
+    }
+
+  return cg_context;
+}
+
+void
+_gdk_macos_surface_release_context (GdkMacosSurface *self,
+                                    CGContextRef     cg_context)
+{
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+
+  CGContextRestoreGState (cg_context);
+  CGContextSetAllowsAntialiasing (cg_context, TRUE);
+}
+
+void
+_gdk_macos_surface_synthesize_null_key (GdkMacosSurface *self)
+{
+  GdkTranslatedKey translated = {0};
+  GdkTranslatedKey no_lock = {0};
+  GdkDisplay *display;
+  GdkEvent *event;
+  GdkSeat *seat;
+
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+
+  translated.keyval = GDK_KEY_VoidSymbol;
+  no_lock.keyval = GDK_KEY_VoidSymbol;
+
+  display = gdk_surface_get_display (GDK_SURFACE (self));
+  seat = gdk_display_get_default_seat (display);
+  event = gdk_key_event_new (GDK_KEY_PRESS,
+                             GDK_SURFACE (self),
+                             gdk_seat_get_keyboard (seat),
+                             NULL,
+                             GDK_CURRENT_TIME,
+                             0,
+                             0,
+                             FALSE,
+                             &translated,
+                             &no_lock);
+  _gdk_event_queue_append (display, event);
+}
+
+void
+_gdk_macos_surface_move (GdkMacosSurface *self,
+                         int              x,
+                         int              y)
+{
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+
+  _gdk_macos_surface_move_resize (self, x, y, -1, -1);
+}
+
+void
+_gdk_macos_surface_move_resize (GdkMacosSurface *self,
+                                int              x,
+                                int              y,
+                                int              width,
+                                int              height)
+{
+  GdkSurface *surface = (GdkSurface *)self;
+  GdkDisplay *display;
+  NSRect content_rect;
+  NSRect frame_rect;
+  gboolean size_changed;
+
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+
+  if ((x == -1 || (x == self->root_x)) &&
+      (y == -1 || (y == self->root_y)) &&
+      (width == -1 || (width == surface->width)) &&
+      (height == -1 || (height == surface->height)))
+    return;
+
+  display = gdk_surface_get_display (surface);
+
+  if (width == -1)
+    width = surface->width;
+
+  if (height == -1)
+    height = surface->height;
+
+  if (x == -1)
+    x = self->root_x;
+
+  if (y == -1)
+    y = self->root_y;
+
+  size_changed = height != surface->height || width != surface->width;
+
+  if (GDK_IS_MACOS_SURFACE (surface->parent))
+    {
+      surface->x = x - GDK_MACOS_SURFACE (surface->parent)->root_x;
+      surface->y = y - GDK_MACOS_SURFACE (surface->parent)->root_y;
+    }
+  else
+    {
+      surface->x = x;
+      surface->y = y;
+    }
+
+  _gdk_macos_display_to_display_coords (GDK_MACOS_DISPLAY (display),
+                                        x, y + height, &x, &y);
+
+  content_rect = NSMakeRect (x, y, width, height);
+  frame_rect = [self->window frameRectForContentRect:content_rect];
+  [self->window setFrame:frame_rect display:YES];
+
+  if (size_changed)
+    gdk_surface_invalidate_rect (surface, NULL);
+}
+
+gboolean
+_gdk_macos_surface_is_tracking (GdkMacosSurface *self,
+                                NSTrackingArea  *area)
+{
+  GdkMacosBaseView *view;
+
+  g_return_val_if_fail (GDK_IS_MACOS_SURFACE (self), FALSE);
+
+  if (self->window == NULL)
+    return FALSE;
+
+  view = (GdkMacosBaseView *)[self->window contentView];
+  if (view == NULL)
+    return FALSE;
+
+  return [view trackingArea] == area;
+}
+
+void
+_gdk_macos_surface_monitor_changed (GdkMacosSurface *self)
+{
+  GListModel *monitors;
+  GdkRectangle rect;
+  GdkRectangle intersect;
+  GdkDisplay *display;
+  GdkMonitor *monitor;
+  guint n_monitors;
+
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+
+  rect.x = self->root_x;
+  rect.y = self->root_y;
+  rect.width = GDK_SURFACE (self)->width;
+  rect.height = GDK_SURFACE (self)->height;
+
+  for (guint i = self->monitors->len; i > 0; i--)
+    {
+      monitor = g_ptr_array_index (self->monitors, i-1);
+
+      if (!gdk_rectangle_intersect (&monitor->geometry, &rect, &intersect))
+        {
+          g_object_ref (monitor);
+          g_ptr_array_remove_index (self->monitors, i-1);
+          gdk_surface_leave_monitor (GDK_SURFACE (self), monitor);
+          g_object_unref (monitor);
+        }
+    }
+
+  display = gdk_surface_get_display (GDK_SURFACE (self));
+  monitors = gdk_display_get_monitors (display);
+  n_monitors = g_list_model_get_n_items (monitors);
+
+  for (guint i = 0; i < n_monitors; i++)
+    {
+      monitor = g_list_model_get_item (monitors, i);
+
+      if (!g_ptr_array_find (self->monitors, monitor, NULL))
+        {
+          gdk_surface_enter_monitor (GDK_SURFACE (self), monitor);
+          g_ptr_array_add (self->monitors, g_object_ref (monitor));
+        }
+
+      g_object_unref (monitor);
+    }
+}
+
+GdkMonitor *
+_gdk_macos_surface_get_best_monitor (GdkMacosSurface *self)
+{
+  GdkMonitor *best = NULL;
+  GdkRectangle rect;
+  int best_area = 0;
+
+  g_return_val_if_fail (GDK_IS_MACOS_SURFACE (self), NULL);
+
+  rect.x = self->root_x;
+  rect.y = self->root_y;
+  rect.width = GDK_SURFACE (self)->width;
+  rect.height = GDK_SURFACE (self)->height;
+
+  for (guint i = 0; i < self->monitors->len; i++)
+    {
+      GdkMonitor *monitor = g_ptr_array_index (self->monitors, i);
+      GdkRectangle intersect;
+
+      if (gdk_rectangle_intersect (&monitor->geometry, &rect, &intersect))
+        {
+          int area = intersect.width * intersect.height;
+
+          if (area > best_area)
+            {
+              best = monitor;
+              best_area = area;
+            }
+        }
+    }
+
+  return best;
+}
+
+NSView *
+_gdk_macos_surface_get_view (GdkMacosSurface *self)
+{
+  g_return_val_if_fail (GDK_IS_MACOS_SURFACE (self), NULL);
+
+  if (self->window == NULL)
+    return NULL;
+
+  return [self->window contentView];
+}
+
+void
+_gdk_macos_surface_set_opacity (GdkMacosSurface *self,
+                                double           opacity)
+{
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+
+  if (self->window != NULL)
+    [self->window setAlphaValue:opacity];
+}
+
+void
+_gdk_macos_surface_get_root_coords (GdkMacosSurface *self,
+                                    int             *x,
+                                    int             *y)
+{
+  GdkSurface *surface;
+  int out_x = 0;
+  int out_y = 0;
+
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+
+  for (surface = GDK_SURFACE (self); surface; surface = surface->parent)
+    {
+      out_x += surface->x;
+      out_y += surface->y;
+    }
+
+  if (x)
+    *x = out_x;
+
+  if (y)
+    *y = out_y;
+}
diff --git a/gdk/macos/gdkmacossurface.h b/gdk/macos/gdkmacossurface.h
new file mode 100644 (file)
index 0000000..4702872
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_SURFACE_H__
+#define __GDK_MACOS_SURFACE_H__
+
+#if !defined (__GDKMACOS_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gdk/macos/gdkmacos.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GdkMacosSurface GdkMacosSurface;
+typedef struct _GdkMacosSurfaceClass GdkMacosSurfaceClass;
+
+#define GDK_TYPE_MACOS_SURFACE       (gdk_macos_surface_get_type())
+#define GDK_MACOS_SURFACE(object)    (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_SURFACE, GdkMacosSurface))
+#define GDK_IS_MACOS_SURFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_SURFACE))
+
+GDK_AVAILABLE_IN_ALL
+GType gdk_macos_surface_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_SURFACE_H__ */
diff --git a/gdk/macos/gdkmacostoplevelsurface-private.h b/gdk/macos/gdkmacostoplevelsurface-private.h
new file mode 100644 (file)
index 0000000..d786660
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_TOPLEVEL_SURFACE_PRIVATE_H__
+#define __GDK_MACOS_TOPLEVEL_SURFACE_PRIVATE_H__
+
+#include "gdkmacossurface-private.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GdkMacosToplevelSurface      GdkMacosToplevelSurface;
+typedef struct _GdkMacosToplevelSurfaceClass GdkMacosToplevelSurfaceClass;
+
+#define GDK_TYPE_MACOS_TOPLEVEL_SURFACE       (_gdk_macos_toplevel_surface_get_type())
+#define GDK_MACOS_TOPLEVEL_SURFACE(object)    (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_TOPLEVEL_SURFACE, GdkMacosToplevelSurface))
+#define GDK_IS_MACOS_TOPLEVEL_SURFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_TOPLEVEL_SURFACE))
+
+GType            _gdk_macos_toplevel_surface_get_type           (void);
+GdkMacosSurface *_gdk_macos_toplevel_surface_new                (GdkMacosDisplay *display,
+                                                                 GdkSurface      *parent,
+                                                                 GdkFrameClock   *frame_clock,
+                                                                 int              x,
+                                                                 int              y,
+                                                                 int              width,
+                                                                 int              height);
+void             _gdk_macos_toplevel_surface_attach_to_parent   (GdkMacosToplevelSurface *self);
+void             _gdk_macos_toplevel_surface_detach_from_parent (GdkMacosToplevelSurface *self);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_TOPLEVEL_SURFACE_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacostoplevelsurface.c b/gdk/macos/gdkmacostoplevelsurface.c
new file mode 100644 (file)
index 0000000..8407636
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#import "GdkMacosWindow.h"
+
+#include "gdkinternals.h"
+#include "gdktoplevelprivate.h"
+
+#include "gdkmacosdisplay-private.h"
+#include "gdkmacostoplevelsurface-private.h"
+#include "gdkmacosutils-private.h"
+
+struct _GdkMacosToplevelSurface
+{
+  GdkMacosSurface parent_instance;
+  guint           decorated : 1;
+};
+
+struct _GdkMacosToplevelSurfaceClass
+{
+  GdkMacosSurfaceClass parent_instance;
+};
+
+static void
+_gdk_macos_toplevel_surface_fullscreen (GdkMacosToplevelSurface *self)
+{
+  NSWindow *window;
+
+  g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
+
+  window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
+
+  if (([window styleMask] & NSWindowStyleMaskFullScreen) == 0)
+    [window toggleFullScreen:window];
+}
+
+static void
+_gdk_macos_toplevel_surface_unfullscreen (GdkMacosToplevelSurface *self)
+{
+  NSWindow *window;
+
+  g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
+
+  window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
+
+  if (([window styleMask] & NSWindowStyleMaskFullScreen) != 0)
+    [window toggleFullScreen:window];
+}
+
+static void
+_gdk_macos_toplevel_surface_maximize (GdkMacosToplevelSurface *self)
+{
+  NSWindow *window;
+
+  g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
+
+  window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
+
+  if (![window isZoomed])
+    [window zoom:window];
+}
+
+static void
+_gdk_macos_toplevel_surface_unmaximize (GdkMacosToplevelSurface *self)
+{
+  NSWindow *window;
+
+  g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
+
+  window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
+
+  if ([window isZoomed])
+    [window zoom:window];
+}
+
+static gboolean
+_gdk_macos_toplevel_surface_present (GdkToplevel       *toplevel,
+                                     int                width,
+                                     int                height,
+                                     GdkToplevelLayout *layout)
+{
+  GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)toplevel;
+  NSWindow *nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
+  GdkGeometry geometry;
+  GdkSurfaceHints mask;
+  NSWindowStyleMask style_mask;
+
+  g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
+  g_assert (GDK_IS_MACOS_WINDOW (nswindow));
+
+  style_mask = [nswindow styleMask];
+
+  if (gdk_toplevel_layout_get_resizable (layout))
+    {
+      geometry.min_width = gdk_toplevel_layout_get_min_width (layout);
+      geometry.min_height = gdk_toplevel_layout_get_min_height (layout);
+      mask = GDK_HINT_MIN_SIZE;
+
+      /* Only set 'Resizable' mask to get native resize zones if the window is
+       * titled, otherwise we do this internally for CSD and do not need
+       * NSWindow to do it for us. Additionally, it can mess things up when
+       * doing a window resize since it can cause mouseDown to get passed
+       * through to the next window.
+       */
+      if ((style_mask & NSWindowStyleMaskTitled) != 0)
+        style_mask |= NSWindowStyleMaskResizable;
+      else
+        style_mask &= ~NSWindowStyleMaskResizable;
+    }
+  else
+    {
+      geometry.max_width = geometry.min_width = width;
+      geometry.max_height = geometry.min_height = height;
+      mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
+
+      style_mask &= ~NSWindowStyleMaskResizable;
+    }
+
+  if (style_mask != [nswindow styleMask])
+    [nswindow setStyleMask:style_mask];
+
+  _gdk_macos_surface_set_geometry_hints (GDK_MACOS_SURFACE (self), &geometry, mask);
+  gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height);
+  _gdk_macos_surface_resize (GDK_MACOS_SURFACE (self), width, height);
+
+  /* Maximized state */
+  if (gdk_toplevel_layout_get_maximized (layout))
+    _gdk_macos_toplevel_surface_maximize (self);
+  else
+    _gdk_macos_toplevel_surface_unmaximize (self);
+
+  /* Fullscreen state */
+  if (gdk_toplevel_layout_get_fullscreen (layout))
+    _gdk_macos_toplevel_surface_fullscreen (self);
+  else
+    _gdk_macos_toplevel_surface_unfullscreen (self);
+
+  if (GDK_SURFACE (self)->transient_for != NULL)
+    {
+    }
+  else
+    {
+      if (!self->decorated &&
+          !GDK_MACOS_SURFACE (self)->did_initial_present &&
+          GDK_SURFACE (self)->x == 0 &&
+          GDK_SURFACE (self)->y == 0 &&
+          (GDK_MACOS_SURFACE (self)->shadow_left ||
+           GDK_MACOS_SURFACE (self)->shadow_top))
+        {
+          GdkMonitor *monitor = _gdk_macos_surface_get_best_monitor (GDK_MACOS_SURFACE (self));
+          int x = GDK_SURFACE (self)->x;
+          int y = GDK_SURFACE (self)->y;
+
+          if (monitor != NULL)
+            {
+              GdkRectangle visible;
+
+              gdk_monitor_get_workarea (monitor, &visible);
+
+              if (x < visible.x)
+                x = visible.x;
+
+              if (y < visible.y)
+                y = visible.y;
+            }
+
+          x -= GDK_MACOS_SURFACE (self)->shadow_left;
+          y -= GDK_MACOS_SURFACE (self)->shadow_top;
+
+          _gdk_macos_surface_move (GDK_MACOS_SURFACE (self), x, y);
+        }
+    }
+
+  _gdk_macos_surface_show (GDK_MACOS_SURFACE (self));
+
+  GDK_MACOS_SURFACE (self)->did_initial_present = TRUE;
+
+  return TRUE;
+}
+
+static gboolean
+_gdk_macos_toplevel_surface_minimize (GdkToplevel *toplevel)
+{
+  GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)toplevel;
+  NSWindow *window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
+  [window miniaturize:window];
+  return TRUE;
+}
+
+static gboolean
+_gdk_macos_toplevel_surface_lower (GdkToplevel *toplevel)
+{
+  GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)toplevel;
+  NSWindow *window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
+  [window orderBack:window];
+  return TRUE;
+}
+
+static void
+_gdk_macos_toplevel_surface_focus (GdkToplevel *toplevel,
+                                   guint32      timestamp)
+{
+  GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)toplevel;
+  NSWindow *nswindow;
+
+  if (GDK_SURFACE_DESTROYED (self))
+    return;
+
+  nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
+  [nswindow makeKeyAndOrderFront:nswindow];
+}
+
+static void
+_gdk_macos_toplevel_surface_begin_resize (GdkToplevel    *toplevel,
+                                          GdkSurfaceEdge  edge,
+                                          GdkDevice      *device,
+                                          int             button,
+                                          double          root_x,
+                                          double          root_y,
+                                          guint32         timestamp)
+{
+  NSWindow *nswindow;
+
+  g_assert (GDK_IS_MACOS_SURFACE (toplevel));
+
+  if (GDK_SURFACE_DESTROYED (toplevel))
+    return;
+
+  /* Release passive grab */
+  if (button != 0)
+    gdk_seat_ungrab (gdk_device_get_seat (device));
+
+  if ((nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (toplevel))))
+    [(GdkMacosWindow *)nswindow beginManualResize:edge];
+}
+
+static void
+_gdk_macos_toplevel_surface_begin_move (GdkToplevel *toplevel,
+                                        GdkDevice   *device,
+                                        int          button,
+                                        double       root_x,
+                                        double       root_y,
+                                        guint32      timestamp)
+{
+  NSWindow *nswindow;
+
+  g_assert (GDK_IS_MACOS_SURFACE (toplevel));
+
+  if (GDK_SURFACE_DESTROYED (toplevel))
+    return;
+
+  /* Release passive grab */
+  if (button != 0)
+    gdk_seat_ungrab (gdk_device_get_seat (device));
+
+  if ((nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (toplevel))))
+    [(GdkMacosWindow *)nswindow beginManualMove];
+}
+
+
+static void
+toplevel_iface_init (GdkToplevelInterface *iface)
+{
+  iface->present = _gdk_macos_toplevel_surface_present;
+  iface->minimize = _gdk_macos_toplevel_surface_minimize;
+  iface->lower = _gdk_macos_toplevel_surface_lower;
+  iface->focus = _gdk_macos_toplevel_surface_focus;
+  iface->begin_resize = _gdk_macos_toplevel_surface_begin_resize;
+  iface->begin_move = _gdk_macos_toplevel_surface_begin_move;
+}
+
+G_DEFINE_TYPE_WITH_CODE (GdkMacosToplevelSurface, _gdk_macos_toplevel_surface, GDK_TYPE_MACOS_SURFACE,
+                         G_IMPLEMENT_INTERFACE (GDK_TYPE_TOPLEVEL, toplevel_iface_init))
+
+enum {
+  PROP_0,
+  LAST_PROP
+};
+
+static void
+_gdk_macos_toplevel_surface_set_transient_for (GdkMacosToplevelSurface *self,
+                                               GdkMacosSurface         *parent)
+{
+  g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
+  g_assert (!parent || GDK_IS_MACOS_SURFACE (parent));
+
+  _gdk_macos_toplevel_surface_detach_from_parent (self);
+  g_clear_object (&GDK_SURFACE (self)->transient_for);
+
+  if (g_set_object (&GDK_SURFACE (self)->transient_for, GDK_SURFACE (parent)))
+    _gdk_macos_toplevel_surface_attach_to_parent (self);
+}
+
+static void
+_gdk_macos_toplevel_surface_set_decorated (GdkMacosToplevelSurface *self,
+                                           gboolean                 decorated)
+{
+  g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
+
+  decorated = !!decorated;
+
+  if (decorated != self->decorated)
+    {
+      NSWindow *window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
+      self->decorated = decorated;
+      [(GdkMacosWindow *)window setDecorated:(BOOL)decorated];
+    }
+}
+
+static void
+_gdk_macos_toplevel_surface_hide (GdkSurface *surface)
+{
+  GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)surface;
+
+  _gdk_macos_toplevel_surface_detach_from_parent (self);
+
+  GDK_SURFACE_CLASS (_gdk_macos_toplevel_surface_parent_class)->hide (surface);
+}
+
+static void
+_gdk_macos_toplevel_surface_destroy (GdkSurface *surface,
+                                     gboolean    foreign_destroy)
+{
+  GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)surface;
+
+  g_clear_object (&GDK_SURFACE (self)->transient_for);
+
+  GDK_SURFACE_CLASS (_gdk_macos_toplevel_surface_parent_class)->destroy (surface, foreign_destroy);
+}
+
+static void
+_gdk_macos_toplevel_surface_get_property (GObject    *object,
+                                          guint       prop_id,
+                                          GValue     *value,
+                                          GParamSpec *pspec)
+{
+  GdkSurface *surface = GDK_SURFACE (object);
+  GdkMacosSurface *base = GDK_MACOS_SURFACE (surface);
+  GdkMacosToplevelSurface *toplevel = GDK_MACOS_TOPLEVEL_SURFACE (base);
+
+  switch (prop_id)
+    {
+    case LAST_PROP + GDK_TOPLEVEL_PROP_STATE:
+      g_value_set_flags (value, surface->state);
+      break;
+
+    case LAST_PROP + GDK_TOPLEVEL_PROP_TITLE:
+      g_value_set_string (value, _gdk_macos_surface_get_title (base));
+      break;
+
+    case LAST_PROP + GDK_TOPLEVEL_PROP_STARTUP_ID:
+      g_value_set_string (value, "");
+      break;
+
+    case LAST_PROP + GDK_TOPLEVEL_PROP_TRANSIENT_FOR:
+      g_value_set_object (value, GDK_SURFACE (toplevel)->transient_for);
+      break;
+
+    case LAST_PROP + GDK_TOPLEVEL_PROP_MODAL:
+      g_value_set_boolean (value, GDK_SURFACE (toplevel)->modal_hint);
+      break;
+
+    case LAST_PROP + GDK_TOPLEVEL_PROP_ICON_LIST:
+      g_value_set_pointer (value, NULL);
+      break;
+
+    case LAST_PROP + GDK_TOPLEVEL_PROP_DECORATED:
+      g_value_set_boolean (value, toplevel->decorated);
+      break;
+
+    case LAST_PROP + GDK_TOPLEVEL_PROP_DELETABLE:
+      break;
+
+    case LAST_PROP + GDK_TOPLEVEL_PROP_FULLSCREEN_MODE:
+      g_value_set_enum (value, surface->fullscreen_mode);
+      break;
+
+    case LAST_PROP + GDK_TOPLEVEL_PROP_SHORTCUTS_INHIBITED:
+      g_value_set_boolean (value, surface->shortcuts_inhibited);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+_gdk_macos_toplevel_surface_set_property (GObject      *object,
+                                          guint         prop_id,
+                                          const GValue *value,
+                                          GParamSpec   *pspec)
+{
+  GdkSurface *surface = GDK_SURFACE (object);
+  GdkMacosSurface *base = GDK_MACOS_SURFACE (surface);
+  GdkMacosToplevelSurface *toplevel = GDK_MACOS_TOPLEVEL_SURFACE (base);
+
+  switch (prop_id)
+    {
+    case LAST_PROP + GDK_TOPLEVEL_PROP_TITLE:
+      _gdk_macos_surface_set_title (base, g_value_get_string (value));
+      g_object_notify_by_pspec (G_OBJECT (surface), pspec);
+      break;
+
+    case LAST_PROP + GDK_TOPLEVEL_PROP_STARTUP_ID:
+      break;
+
+    case LAST_PROP + GDK_TOPLEVEL_PROP_TRANSIENT_FOR:
+      _gdk_macos_toplevel_surface_set_transient_for (toplevel, g_value_get_object (value));
+      g_object_notify_by_pspec (G_OBJECT (surface), pspec);
+      break;
+
+    case LAST_PROP + GDK_TOPLEVEL_PROP_MODAL:
+      GDK_SURFACE (surface)->modal_hint = g_value_get_boolean (value);
+      g_object_notify_by_pspec (G_OBJECT (surface), pspec);
+      break;
+
+    case LAST_PROP + GDK_TOPLEVEL_PROP_ICON_LIST:
+      break;
+
+    case LAST_PROP + GDK_TOPLEVEL_PROP_DECORATED:
+      _gdk_macos_toplevel_surface_set_decorated (toplevel, g_value_get_boolean (value));
+      break;
+
+    case LAST_PROP + GDK_TOPLEVEL_PROP_DELETABLE:
+      break;
+
+    case LAST_PROP + GDK_TOPLEVEL_PROP_FULLSCREEN_MODE:
+      surface->fullscreen_mode = g_value_get_enum (value);
+      g_object_notify_by_pspec (G_OBJECT (surface), pspec);
+      break;
+
+    case LAST_PROP + GDK_TOPLEVEL_PROP_SHORTCUTS_INHIBITED:
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+_gdk_macos_toplevel_surface_class_init (GdkMacosToplevelSurfaceClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkSurfaceClass *surface_class = GDK_SURFACE_CLASS (klass);
+
+  object_class->get_property = _gdk_macos_toplevel_surface_get_property;
+  object_class->set_property = _gdk_macos_toplevel_surface_set_property;
+
+  surface_class->destroy = _gdk_macos_toplevel_surface_destroy;
+  surface_class->hide = _gdk_macos_toplevel_surface_hide;
+
+  gdk_toplevel_install_properties (object_class, LAST_PROP);
+}
+
+static void
+_gdk_macos_toplevel_surface_init (GdkMacosToplevelSurface *self)
+{
+  self->decorated = TRUE;
+}
+
+GdkMacosSurface *
+_gdk_macos_toplevel_surface_new (GdkMacosDisplay *display,
+                                 GdkSurface      *parent,
+                                 GdkFrameClock   *frame_clock,
+                                 int              x,
+                                 int              y,
+                                 int              width,
+                                 int              height)
+{
+  GDK_BEGIN_MACOS_ALLOC_POOL;
+
+  GdkMacosWindow *window;
+  GdkMacosSurface *self;
+  NSScreen *screen;
+  NSUInteger style_mask;
+  NSRect content_rect;
+  NSRect screen_rect;
+  int nx;
+  int ny;
+
+  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
+  g_return_val_if_fail (!frame_clock || GDK_IS_FRAME_CLOCK (frame_clock), NULL);
+  g_return_val_if_fail (!parent || GDK_IS_MACOS_SURFACE (parent), NULL);
+
+  style_mask = (NSWindowStyleMaskTitled |
+                NSWindowStyleMaskClosable |
+                NSWindowStyleMaskMiniaturizable |
+                NSWindowStyleMaskResizable);
+
+  _gdk_macos_display_to_display_coords (display, x, y, &nx, &ny);
+
+  screen = _gdk_macos_display_get_screen_at_display_coords (display, nx, ny);
+  screen_rect = [screen visibleFrame];
+  nx -= screen_rect.origin.x;
+  ny -= screen_rect.origin.y;
+  content_rect = NSMakeRect (nx, ny - height, width, height);
+
+  window = [[GdkMacosWindow alloc] initWithContentRect:content_rect
+                                             styleMask:style_mask
+                                               backing:NSBackingStoreBuffered
+                                                 defer:NO
+                                                screen:screen];
+
+  self = g_object_new (GDK_TYPE_MACOS_TOPLEVEL_SURFACE,
+                       "display", display,
+                       "frame-clock", frame_clock,
+                       "native", window,
+                       NULL);
+
+  GDK_END_MACOS_ALLOC_POOL;
+
+  return g_steal_pointer (&self);
+}
+
+void
+_gdk_macos_toplevel_surface_attach_to_parent (GdkMacosToplevelSurface *self)
+{
+  GdkSurface *surface = (GdkSurface *)self;
+
+  g_return_if_fail (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
+
+  if (GDK_SURFACE_DESTROYED (surface))
+    return;
+
+  if (surface->transient_for != NULL &&
+      !GDK_SURFACE_DESTROYED (surface->transient_for))
+    {
+      NSWindow *parent = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface->transient_for));
+      NSWindow *window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
+
+      [parent addChildWindow:window ordered:NSWindowAbove];
+
+      if (GDK_SURFACE (self)->modal_hint)
+        [window setLevel:NSModalPanelWindowLevel];
+
+      _gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (surface->display));
+    }
+}
+
+void
+_gdk_macos_toplevel_surface_detach_from_parent (GdkMacosToplevelSurface *self)
+{
+  GdkSurface *surface = (GdkSurface *)self;
+
+  g_return_if_fail (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
+
+  if (GDK_SURFACE_DESTROYED (surface))
+    return;
+
+  if (surface->transient_for != NULL &&
+      !GDK_SURFACE_DESTROYED (surface->transient_for))
+    {
+      NSWindow *parent = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface->transient_for));
+      NSWindow *window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
+
+      [parent removeChildWindow:window];
+      [window setLevel:NSNormalWindowLevel];
+
+      _gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (surface->display));
+    }
+}
diff --git a/gdk/macos/gdkmacosutils-private.h b/gdk/macos/gdkmacosutils-private.h
new file mode 100644 (file)
index 0000000..678982b
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2020 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_UTILS_PRIVATE_H__
+#define __GDK_MACOS_UTILS_PRIVATE_H__
+
+#include <AppKit/AppKit.h>
+#include <gdk/gdk.h>
+
+#define GDK_BEGIN_MACOS_ALLOC_POOL NSAutoreleasePool *_pool = [[NSAutoreleasePool alloc] init]
+#define GDK_END_MACOS_ALLOC_POOL   [_pool release]
+
+static inline gboolean
+queue_contains (GQueue *queue,
+                GList  *link_)
+{
+  return queue->head == link_ || link_->prev || link_->next;
+}
+
+#endif /* __GDK_MACOS_UTILS_PRIVATE_H__ */
diff --git a/gdk/macos/meson.build b/gdk/macos/meson.build
new file mode 100644 (file)
index 0000000..ef9f21e
--- /dev/null
@@ -0,0 +1,62 @@
+gdk_macos_sources = files([
+  'edgesnapping.c',
+
+  'gdkdisplaylinksource.c',
+  'gdkmacoscairocontext.c',
+  'gdkmacosclipboard.c',
+  'gdkmacoscursor.c',
+  'gdkmacosdevice.c',
+  'gdkmacosdisplay.c',
+  'gdkmacosdisplay-settings.c',
+  'gdkmacosdisplay-translate.c',
+  'gdkmacosdrag.c',
+  'gdkmacosdragsurface.c',
+  'gdkmacosglcontext.c',
+  'gdkmacoseventsource.c',
+  'gdkmacoskeymap.c',
+  'gdkmacosmonitor.c',
+  'gdkmacospopupsurface.c',
+  'gdkmacosseat.c',
+  'gdkmacossurface.c',
+  'gdkmacostoplevelsurface.c',
+
+  'GdkMacosBaseView.c',
+  'GdkMacosCairoView.c',
+  'GdkMacosCairoSubview.c',
+  'GdkMacosGLLayer.c',
+  'GdkMacosWindow.c',
+])
+
+gdk_macos_public_headers = files([
+  'gdkmacosdevice.h',
+  'gdkmacosdisplay.h',
+  'gdkmacosglcontext.h',
+  'gdkmacoskeymap.h',
+  'gdkmacosmonitor.h',
+  'gdkmacossurface.h',
+])
+
+install_headers(gdk_macos_public_headers, 'gdkmacos.h', subdir: 'gtk-4.0/gdk/macos/')
+
+gdk_macos_frameworks = [
+  'AppKit',
+  'Carbon',
+  'CoreVideo',
+  'CoreServices',
+  'OpenGL',
+  'QuartzCore',
+]
+
+gdk_macos_deps = [
+  dependency('appleframeworks', modules: gdk_macos_frameworks)
+]
+
+libgdk_c_args += ['-xobjective-c']
+
+libgdk_macos = static_library('gdk-macos',
+                              gdk_macos_sources, gdkconfig, gdkenum_h,
+                              include_directories: [ confinc, gdkinc, ],
+                              c_args: libgdk_c_args + common_cflags,
+                              link_args: common_ldflags,
+                              link_with: [],
+                              dependencies: gdk_deps + gdk_macos_deps)
index 972ec0f166d76a55bd00a7c36e7671f829fdac6d..eebc9b2a97b5318ebda5a7e123d7022c66e89b68 100644 (file)
@@ -143,6 +143,7 @@ gdkconfig_cdata.set('GDK_WINDOWING_X11', x11_enabled)
 gdkconfig_cdata.set('GDK_WINDOWING_WAYLAND', wayland_enabled)
 gdkconfig_cdata.set('GDK_WINDOWING_WIN32', win32_enabled)
 gdkconfig_cdata.set('GDK_WINDOWING_BROADWAY', broadway_enabled)
+gdkconfig_cdata.set('GDK_WINDOWING_MACOS', macos_enabled)
 gdkconfig_cdata.set('GDK_RENDERING_VULKAN', have_vulkan)
 
 gdkconfig = configure_file(
@@ -223,7 +224,7 @@ libgdk_c_args = [
 
 gdk_backends = []
 gdk_backends_gen_headers = []  # non-public generated headers
-foreach backend : ['broadway', 'quartz', 'wayland', 'win32', 'x11']
+foreach backend : ['broadway', 'quartz', 'wayland', 'win32', 'x11', 'macos']
   if get_variable('@0@_enabled'.format(backend))
     subdir(backend)
     gdk_deps += get_variable('gdk_@0@_deps'.format(backend))
diff --git a/gdk/quartz/GdkQuartzNSWindow.c b/gdk/quartz/GdkQuartzNSWindow.c
deleted file mode 100644 (file)
index ec52e7f..0000000
+++ /dev/null
@@ -1,845 +0,0 @@
-/* GdkQuartzSurface.m
- *
- * Copyright (C) 2005-2007 Imendio AB
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#import "GdkQuartzNSWindow.h"
-#include "gdkquartzsurface.h"
-#include "gdkdnd-quartz.h"
-#include "gdkprivate-quartz.h"
-
-@implementation GdkQuartzNSWindow
-
-- (void)windowWillClose:(NSNotification*)notification
-{
-  // Clears the delegate when window is going to be closed; since EL
-  // Capitan it is possible that the methods of delegate would get
-  // called after the window has been closed.
-  [self setDelegate:nil];
-}
-
--(BOOL)windowShouldClose:(id)sender
-{
-  GdkSurface *window = [[self contentView] gdkSurface];
-  GdkEvent *event;
-
-  event = gdk_event_new (GDK_DELETE);
-
-  event->any.surface = g_object_ref (window);
-  event->any.send_event = FALSE;
-
-  _gdk_event_queue_append (gdk_display_get_default (), event);
-
-  return NO;
-}
-
--(void)windowWillMiniaturize:(NSNotification *)aNotification
-{
-  GdkSurface *window = [[self contentView] gdkSurface];
-
-  _gdk_quartz_surface_detach_from_parent (window);
-}
-
--(void)windowDidMiniaturize:(NSNotification *)aNotification
-{
-  GdkSurface *window = [[self contentView] gdkSurface];
-
-  gdk_synthesize_surface_state (window, 0, GDK_SURFACE_STATE_MINIMIZED);
-}
-
--(void)windowDidDeminiaturize:(NSNotification *)aNotification
-{
-  GdkSurface *window = [[self contentView] gdkSurface];
-
-  _gdk_quartz_surface_attach_to_parent (window);
-
-  gdk_synthesize_surface_state (window, GDK_SURFACE_STATE_MINIMIZED, 0);
-}
-
--(void)windowDidBecomeKey:(NSNotification *)aNotification
-{
-  GdkSurface *window = [[self contentView] gdkSurface];
-
-  gdk_synthesize_surface_state (window, 0, GDK_SURFACE_STATE_FOCUSED);
-  _gdk_quartz_events_update_focus_window (window, TRUE);
-}
-
--(void)windowDidResignKey:(NSNotification *)aNotification
-{
-  GdkSurface *window = [[self contentView] gdkSurface];
-
-  _gdk_quartz_events_update_focus_window (window, FALSE);
-  gdk_synthesize_surface_state (window, GDK_SURFACE_STATE_FOCUSED, 0);
-}
-
--(void)windowDidBecomeMain:(NSNotification *)aNotification
-{
-  GdkSurface *window = [[self contentView] gdkSurface];
-
-  if (![self isVisible])
-    {
-      /* Note: This is a hack needed because for unknown reasons, hidden
-       * windows get shown when clicking the dock icon when the application
-       * is not already active.
-       */
-      [self orderOut:nil];
-      return;
-    }
-
-  _gdk_quartz_surface_did_become_main (window);
-}
-
--(void)windowDidResignMain:(NSNotification *)aNotification
-{
-  GdkSurface *window;
-
-  window = [[self contentView] gdkSurface];
-  _gdk_quartz_surface_did_resign_main (window);
-}
-
-/* Used in combination with NSLeftMouseUp in sendEvent to keep track
- * of when the window is being moved with the mouse.
- */
--(void)windowWillMove:(NSNotification *)aNotification
-{
-  inMove = YES;
-}
-
--(void)sendEvent:(NSEvent *)event
-{
-  switch ([event type])
-    {
-    case NSLeftMouseUp:
-    {
-      double time = ((double)[event timestamp]) * 1000.0;
-
-      _gdk_quartz_events_break_all_grabs (time);
-      inManualMove = NO;
-      inManualResize = NO;
-      inMove = NO;
-      break;
-    }
-
-    case NSLeftMouseDragged:
-      if ([self trackManualMove] || [self trackManualResize])
-        return;
-      break;
-
-    default:
-      break;
-    }
-
-  [super sendEvent:event];
-}
-
--(BOOL)isInMove
-{
-  return inMove;
-}
-
--(void)checkSendEnterNotify
-{
-  GdkSurface *window = [[self contentView] gdkSurface];
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  /* When a new window has been created, and the mouse
-   * is in the window area, we will not receive an NSMouseEntered
-   * event.  Therefore, we synthesize an enter notify event manually.
-   */
-  if (!initialPositionKnown)
-    {
-      initialPositionKnown = YES;
-
-      if (NSPointInRect ([NSEvent mouseLocation], [self frame]))
-        {
-          NSEvent *event;
-
-          event = [NSEvent enterExitEventWithType: NSMouseEntered
-                                         location: [self mouseLocationOutsideOfEventStream]
-                                    modifierFlags: 0
-                                        timestamp: [[NSApp currentEvent] timestamp]
-                                     windowNumber: [impl->toplevel windowNumber]
-                                          context: NULL
-                                      eventNumber: 0
-                                   trackingNumber: [impl->view trackingRect]
-                                         userData: nil];
-
-          [NSApp postEvent:event atStart:NO];
-        }
-    }
-}
-
--(void)windowDidMove:(NSNotification *)aNotification
-{
-  GdkSurface *window = [[self contentView] gdkSurface];
-  GdkEvent *event;
-
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  gboolean maximized = gdk_surface_get_state (window) & GDK_SURFACE_STATE_MAXIMIZED;
-
-  /* In case the window is changed when maximized remove the maximized state */
-  if (maximized && !inMaximizeTransition && !NSEqualRects (lastMaximizedFrame, [self frame]))
-    {
-      gdk_synthesize_surface_state (window,
-                                   GDK_SURFACE_STATE_MAXIMIZED,
-                                   0);
-    }
-
-  _gdk_quartz_surface_update_position (window);
-
-  /* Synthesize a configure event */
-  event = gdk_event_new (GDK_CONFIGURE);
-  event->configure.window = g_object_ref (window);
-  event->configure.x = window->x;
-  event->configure.y = window->y;
-  event->configure.width = window->width;
-  event->configure.height = window->height;
-
-  _gdk_event_queue_append (gdk_display_get_default (), event);
-
-  [self checkSendEnterNotify];
-}
-
--(void)windowDidResize:(NSNotification *)aNotification
-{
-  NSRect content_rect = [self contentRectForFrameRect:[self frame]];
-  GdkSurface *window = [[self contentView] gdkSurface];
-  GdkEvent *event;
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  gboolean maximized = gdk_surface_get_state (window) & GDK_SURFACE_STATE_MAXIMIZED;
-
-  /* see same in windowDidMove */
-  if (maximized && !inMaximizeTransition && !NSEqualRects (lastMaximizedFrame, [self frame]))
-    {
-      gdk_synthesize_surface_state (window,
-                                   GDK_SURFACE_STATE_MAXIMIZED,
-                                   0);
-    }
-
-  window->width = content_rect.size.width;
-  window->height = content_rect.size.height;
-
-  /* Certain resize operations (e.g. going fullscreen), also move the
-   * origin of the window.
-   */
-  _gdk_quartz_surface_update_position (window);
-
-  [[self contentView] setFrame:NSMakeRect (0, 0, window->width, window->height)];
-
-  _gdk_surface_update_size (window);
-
-  /* Synthesize a configure event */
-  event = gdk_event_new (GDK_CONFIGURE);
-  event->configure.window = g_object_ref (window);
-  event->configure.x = window->x;
-  event->configure.y = window->y;
-  event->configure.width = window->width;
-  event->configure.height = window->height;
-
-  _gdk_event_queue_append (gdk_display_get_default (), event);
-
-  [self checkSendEnterNotify];
-}
-
--(id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag screen:(NSScreen *)screen
-{
-  self = [super initWithContentRect:contentRect
-                         styleMask:styleMask
-                           backing:backingType
-                             defer:flag
-                             screen:screen];
-
-  [self setAcceptsMouseMovedEvents:YES];
-  [self setDelegate:self];
-  [self setReleasedWhenClosed:YES];
-
-  return self;
-}
-
--(BOOL)canBecomeMainWindow
-{
-  GdkSurface *window = [[self contentView] gdkSurface];
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  switch (impl->type_hint)
-    {
-    case GDK_SURFACE_TYPE_HINT_NORMAL:
-    case GDK_SURFACE_TYPE_HINT_DIALOG:
-      return YES;
-      
-    case GDK_SURFACE_TYPE_HINT_MENU:
-    case GDK_SURFACE_TYPE_HINT_TOOLBAR:
-    case GDK_SURFACE_TYPE_HINT_SPLASHSCREEN:
-    case GDK_SURFACE_TYPE_HINT_UTILITY:
-    case GDK_SURFACE_TYPE_HINT_DOCK:
-    case GDK_SURFACE_TYPE_HINT_DESKTOP:
-    case GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU:
-    case GDK_SURFACE_TYPE_HINT_POPUP_MENU:
-    case GDK_SURFACE_TYPE_HINT_TOOLTIP:
-    case GDK_SURFACE_TYPE_HINT_NOTIFICATION:
-    case GDK_SURFACE_TYPE_HINT_COMBO:
-    case GDK_SURFACE_TYPE_HINT_DND:
-      return NO;
-    }
-  
-  return YES;
-}
-
--(BOOL)canBecomeKeyWindow
-{
-  GdkSurface *window = [[self contentView] gdkSurface];
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (!window->accept_focus)
-    return NO;
-
-  /* Popup windows should not be able to get focused in the window
-   * manager sense, it's only handled through grabs.
-   */
-  if (window->surface_type == GDK_SURFACE_TEMP)
-    return NO;
-
-  switch (impl->type_hint)
-    {
-    case GDK_SURFACE_TYPE_HINT_NORMAL:
-    case GDK_SURFACE_TYPE_HINT_DIALOG:
-    case GDK_SURFACE_TYPE_HINT_MENU:
-    case GDK_SURFACE_TYPE_HINT_TOOLBAR:
-    case GDK_SURFACE_TYPE_HINT_UTILITY:
-    case GDK_SURFACE_TYPE_HINT_DOCK:
-    case GDK_SURFACE_TYPE_HINT_DESKTOP:
-    case GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU:
-    case GDK_SURFACE_TYPE_HINT_POPUP_MENU:
-    case GDK_SURFACE_TYPE_HINT_COMBO:
-      return YES;
-      
-    case GDK_SURFACE_TYPE_HINT_SPLASHSCREEN:
-    case GDK_SURFACE_TYPE_HINT_TOOLTIP:
-    case GDK_SURFACE_TYPE_HINT_NOTIFICATION:
-    case GDK_SURFACE_TYPE_HINT_DND:
-      return NO;
-    }
-  
-  return YES;
-}
-
-- (void)showAndMakeKey:(BOOL)makeKey
-{
-  GdkSurface *window = [[self contentView] gdkSurface];
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  inShowOrHide = YES;
-
-  if (makeKey)
-    [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
-  else
-    [impl->toplevel orderFront:nil];
-
-  inShowOrHide = NO;
-
-  [self checkSendEnterNotify];
-}
-
-- (void)hide
-{
-  GdkSurface *window = [[self contentView] gdkSurface];
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  inShowOrHide = YES;
-  [impl->toplevel orderOut:nil];
-  inShowOrHide = NO;
-
-  initialPositionKnown = NO;
-}
-
-- (BOOL)trackManualMove
-{
-  GdkSurface *window = [[self contentView] gdkSurface];
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  NSPoint currentLocation;
-  NSPoint newOrigin;
-  NSRect screenFrame = [[NSScreen mainScreen] visibleFrame];
-  NSRect windowFrame = [self frame];
-
-  if (!inManualMove)
-    return NO;
-
-  currentLocation = [self convertBaseToScreen:[self mouseLocationOutsideOfEventStream]];
-  newOrigin.x = currentLocation.x - initialMoveLocation.x;
-  newOrigin.y = currentLocation.y - initialMoveLocation.y;
-
-  /* Clamp vertical position to below the menu bar. */
-  if (newOrigin.y + windowFrame.size.height - impl->shadow_top > screenFrame.origin.y + screenFrame.size.height)
-    newOrigin.y = screenFrame.origin.y + screenFrame.size.height - windowFrame.size.height + impl->shadow_top;
-
-  [self setFrameOrigin:newOrigin];
-
-  return YES;
-}
-
-/* Used by gdkevents-quartz.c to decide if our sendEvent() handler above
- * will see the event or if it will be subjected to standard processing
- * by GDK.
-*/
--(BOOL)isInManualResizeOrMove
-{
-  return inManualResize || inManualMove;
-}
-
--(void)beginManualMove
-{
-  NSRect frame = [self frame];
-
-  if (inMove || inManualMove || inManualResize)
-    return;
-
-  inManualMove = YES;
-
-  initialMoveLocation = [self convertBaseToScreen:[self mouseLocationOutsideOfEventStream]];
-  initialMoveLocation.x -= frame.origin.x;
-  initialMoveLocation.y -= frame.origin.y;
-}
-
-- (BOOL)trackManualResize
-{
-  NSPoint mouse_location;
-  NSRect new_frame;
-  float mdx, mdy, dw, dh, dx, dy;
-  NSSize min_size;
-
-  if (!inManualResize || inTrackManualResize)
-    return NO;
-
-  inTrackManualResize = YES;
-
-  mouse_location = [self convertBaseToScreen:[self mouseLocationOutsideOfEventStream]];
-  mdx = initialResizeLocation.x - mouse_location.x;
-  mdy = initialResizeLocation.y - mouse_location.y;
-
-  /* Set how a mouse location delta translates to changes in width,
-   * height and position.
-   */
-  dw = dh = dx = dy = 0.0;
-  if (resizeEdge == GDK_SURFACE_EDGE_EAST ||
-      resizeEdge == GDK_SURFACE_EDGE_NORTH_EAST ||
-      resizeEdge == GDK_SURFACE_EDGE_SOUTH_EAST)
-    {
-      dw = -1.0;
-    }
-  if (resizeEdge == GDK_SURFACE_EDGE_NORTH ||
-      resizeEdge == GDK_SURFACE_EDGE_NORTH_WEST ||
-      resizeEdge == GDK_SURFACE_EDGE_NORTH_EAST)
-    {
-      dh = -1.0;
-    }
-  if (resizeEdge == GDK_SURFACE_EDGE_SOUTH ||
-      resizeEdge == GDK_SURFACE_EDGE_SOUTH_WEST ||
-      resizeEdge == GDK_SURFACE_EDGE_SOUTH_EAST)
-    {
-      dh = 1.0;
-      dy = -1.0;
-    }
-  if (resizeEdge == GDK_SURFACE_EDGE_WEST ||
-      resizeEdge == GDK_SURFACE_EDGE_NORTH_WEST ||
-      resizeEdge == GDK_SURFACE_EDGE_SOUTH_WEST)
-    {
-      dw = 1.0;
-      dx = -1.0;
-    }
-
-  /* Apply changes to the frame captured when we started resizing */
-  new_frame = initialResizeFrame;
-  new_frame.origin.x += mdx * dx;
-  new_frame.origin.y += mdy * dy;
-  new_frame.size.width += mdx * dw;
-  new_frame.size.height += mdy * dh;
-
-  /* In case the resulting window would be too small reduce the
-   * change to both size and position.
-   */
-  min_size = [self contentMinSize];
-
-  if (new_frame.size.width < min_size.width)
-    {
-      if (dx)
-        new_frame.origin.x -= min_size.width - new_frame.size.width;
-      new_frame.size.width = min_size.width;
-    }
-
-  if (new_frame.size.height < min_size.height)
-    {
-      if (dy)
-        new_frame.origin.y -= min_size.height - new_frame.size.height;
-      new_frame.size.height = min_size.height;
-    }
-
-  /* We could also apply aspect ratio:
-     new_frame.size.height = new_frame.size.width / [self aspectRatio].width * [self aspectRatio].height;
-  */
-
-  [self setFrame:new_frame display:YES];
-
-  /* Let the resizing be handled by GTK+. */
-  if (g_main_context_pending (NULL))
-    g_main_context_iteration (NULL, FALSE);
-
-  inTrackManualResize = NO;
-
-  return YES;
-}
-
--(void)beginManualResize:(GdkSurfaceEdge)edge
-{
-  if (inMove || inManualMove || inManualResize)
-    return;
-
-  inManualResize = YES;
-  resizeEdge = edge;
-
-  initialResizeFrame = [self frame];
-  initialResizeLocation = [self convertBaseToScreen:[self mouseLocationOutsideOfEventStream]];
-}
-
-
-
-static GdkDragContext *current_context = NULL;
-
-static GdkDragAction
-drag_operation_to_drag_action (NSDragOperation operation)
-{
-  GdkDragAction result = 0;
-
-  /* GDK and Quartz drag operations do not map 1:1.
-   * This mapping represents about the best that we
-   * can come up.
-   */
-
-  if (operation & NSDragOperationGeneric)
-    result |= GDK_ACTION_MOVE;
-  if (operation & NSDragOperationCopy)
-    result |= GDK_ACTION_COPY;
-  if (operation & NSDragOperationMove)
-    result |= GDK_ACTION_MOVE;
-  if (operation & NSDragOperationLink)
-    result |= GDK_ACTION_LINK;
-
-  return result;
-}
-
-static NSDragOperation
-drag_action_to_drag_operation (GdkDragAction action)
-{
-  NSDragOperation result = 0;
-
-  if (action & GDK_ACTION_COPY)
-    result |= NSDragOperationCopy;
-  if (action & GDK_ACTION_LINK)
-    result |= NSDragOperationLink;
-  if (action & GDK_ACTION_MOVE)
-    result |= NSDragOperationMove;
-
-  return result;
-}
-
-static void
-update_context_from_dragging_info (id <NSDraggingInfo> sender)
-{
-  GdkDragAction action;
-
-  g_assert (current_context != NULL);
-
-  GDK_QUARTZ_DRAG_CONTEXT (current_context)->dragging_info = sender;
-  action = drag_operation_to_drag_action ([sender draggingSourceOperationMask]);
-  gdk_drag_context_set_actions (current_context, action, action);
-}
-
-- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
-{
-  GdkEvent *event;
-  GdkSurface *window;
-
-  if (current_context)
-    g_object_unref (current_context);
-
-  current_context = g_object_new (GDK_TYPE_QUARTZ_DRAG_CONTEXT,
-                                  "device", gdk_seat_get_pointer (gdk_display_get_default_seat (current_context->display)),
-                                  NULL);
-  update_context_from_dragging_info (sender);
-
-  window = [[self contentView] gdkSurface];
-
-  event = gdk_event_new (GDK_DRAG_ENTER);
-  event->dnd.window = g_object_ref (window);
-  event->dnd.send_event = FALSE;
-  event->dnd.context = g_object_ref (current_context);
-  event->dnd.time = GDK_CURRENT_TIME;
-
-  gdk_event_set_device (event, gdk_drag_context_get_device (current_context));
-  gdk_event_set_seat (event, gdk_device_get_seat (gdk_drag_context_get_device (current_context)));
-
-  _gdk_event_emit (event);
-
-  g_object_unref (event);
-
-  return NSDragOperationNone;
-}
-
-- (void)draggingEnded:(id <NSDraggingInfo>)sender
-{
-  /* leave a note for the source about what action was taken */
-  if (_gdk_quartz_drag_source_context && current_context)
-   _gdk_quartz_drag_source_context->action = current_context->action;
-
-  if (current_context)
-    g_object_unref (current_context);
-  current_context = NULL;
-}
-
-- (void)draggingExited:(id <NSDraggingInfo>)sender
-{
-  GdkEvent *event;
-  
-  event = gdk_event_new (GDK_DRAG_LEAVE);
-  event->dnd.window = g_object_ref ([[self contentView] gdkSurface]);
-  event->dnd.send_event = FALSE;
-  event->dnd.context = g_object_ref (current_context);
-  event->dnd.time = GDK_CURRENT_TIME;
-
-  gdk_event_set_device (event, gdk_drag_context_get_device (current_context));
-  gdk_event_set_seat (event, gdk_device_get_seat (gdk_drag_context_get_device (current_context)));
-
-  _gdk_event_emit (event);
-
-  g_object_unref (event);
-  
-  g_object_unref (current_context);
-  current_context = NULL;
-}
-
-- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
-{
-  NSPoint point = [sender draggingLocation];
-  NSPoint screen_point = [self convertBaseToScreen:point];
-  GdkEvent *event;
-  int gx, gy;
-
-  update_context_from_dragging_info (sender);
-  _gdk_quartz_surface_nspoint_to_gdk_xy (screen_point, &gx, &gy);
-
-  event = gdk_event_new (GDK_DRAG_MOTION);
-  event->dnd.window = g_object_ref ([[self contentView] gdkSurface]);
-  event->dnd.send_event = FALSE;
-  event->dnd.context = g_object_ref (current_context);
-  event->dnd.time = GDK_CURRENT_TIME;
-  event->dnd.x_root = gx;
-  event->dnd.y_root = gy;
-
-  gdk_event_set_device (event, gdk_drag_context_get_device (current_context));
-  gdk_event_set_seat (event, gdk_device_get_seat (gdk_drag_context_get_device (current_context)));
-
-  _gdk_event_emit (event);
-
-  g_object_unref (event);
-
-  return drag_action_to_drag_operation (current_context->action);
-}
-
-- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
-{
-  NSPoint point = [sender draggingLocation];
-  NSPoint screen_point = [self convertBaseToScreen:point];
-  GdkEvent *event;
-  int gy, gx;
-
-  update_context_from_dragging_info (sender);
-  _gdk_quartz_surface_nspoint_to_gdk_xy (screen_point, &gx, &gy);
-
-  event = gdk_event_new (GDK_DROP_START);
-  event->dnd.window = g_object_ref ([[self contentView] gdkSurface]);
-  event->dnd.send_event = FALSE;
-  event->dnd.context = g_object_ref (current_context);
-  event->dnd.time = GDK_CURRENT_TIME;
-  event->dnd.x_root = gx;
-  event->dnd.y_root = gy;
-
-  gdk_event_set_device (event, gdk_drag_context_get_device (current_context));
-  gdk_event_set_seat (event, gdk_device_get_seat (gdk_drag_context_get_device (current_context)));
-
-  _gdk_event_emit (event);
-
-  g_object_unref (event);
-
-  g_object_unref (current_context);
-  current_context = NULL;
-
-  return YES;
-}
-
-- (BOOL)wantsPeriodicDraggingUpdates
-{
-  return NO;
-}
-
-- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation
-{
-  GdkEvent *event;
-  GdkDisplay *display;
-  GdkDevice *device;
-
-  g_assert (_gdk_quartz_drag_source_context != NULL);
-
-  event = gdk_event_new (GDK_DROP_FINISHED);
-  event->dnd.window = g_object_ref ([[self contentView] gdkSurface]);
-  event->dnd.send_event = FALSE;
-  event->dnd.context = g_object_ref (_gdk_quartz_drag_source_context);
-
-  display = gdk_surface_get_display (event->dnd.window);
-
-  if (display)
-    {
-      GList* windows, *list;
-      gint gx, gy;
-
-      event->dnd.context->dest_surface = NULL;
-
-      windows = get_toplevels ();
-      _gdk_quartz_surface_nspoint_to_gdk_xy (aPoint, &gx, &gy);
-
-      for (list = windows; list; list = list->next)
-        {
-          GdkSurface* win = (GdkSurface*) list->data;
-          gint wx, wy;
-          gint ww, wh;
-
-          gdk_surface_get_root_origin (win, &wx, &wy);
-          ww = gdk_surface_get_width (win);
-          wh = gdk_surface_get_height (win);
-
-          if (gx > wx && gy > wy && gx <= wx + ww && gy <= wy + wh)
-            event->dnd.context->dest_surface = win;
-        }
-    }
-
-  device = gdk_drag_context_get_device (_gdk_quartz_drag_source_context);
-  gdk_event_set_device (event, device);
-  gdk_event_set_seat (event, gdk_device_get_seat (device));
-
-  _gdk_event_emit (event);
-
-  g_object_unref (event);
-
-  g_object_unref (_gdk_quartz_drag_source_context);
-  _gdk_quartz_drag_source_context = NULL;
-}
-
-#ifdef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
-
-- (void)setStyleMask:(NSUInteger)styleMask
-{
-  gboolean was_fullscreen;
-  gboolean is_fullscreen;
-
-  was_fullscreen = (([self styleMask] & NSFullScreenWindowMask) != 0);
-
-  [super setStyleMask:styleMask];
-
-  is_fullscreen = (([self styleMask] & NSFullScreenWindowMask) != 0);
-
-  if (was_fullscreen != is_fullscreen)
-    _gdk_quartz_surface_update_fullscreen_state ([[self contentView] gdkSurface]);
-}
-
-#endif
-
-- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
-{
-  NSRect rect;
-  GdkSurface *window = [[self contentView] gdkSurface];
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  /* Allow the window to move up "shadow_top" more than normally allowed
-   * by the default impl. This makes it possible to move windows with
-   * client side shadow right up to the screen's menu bar. */
-  rect = [super constrainFrameRect:frameRect toScreen:screen];
-  if (frameRect.origin.y > rect.origin.y)
-    rect.origin.y = MIN (frameRect.origin.y, rect.origin.y + impl->shadow_top);
-
-  return rect;
-}
-
-- (NSRect)windowWillUseStandardFrame:(NSWindow *)nsWindow
-                        defaultFrame:(NSRect)newFrame
-{
-  NSRect screenFrame = [[self screen] visibleFrame];
-  GdkSurface *window = [[self contentView] gdkSurface];
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  gboolean maximized = gdk_surface_get_state (window) & GDK_SURFACE_STATE_MAXIMIZED;
-
-  if (!maximized)
-    return screenFrame;
-  else
-    return lastUnmaximizedFrame;
-}
-
-- (BOOL)windowShouldZoom:(NSWindow *)nsWindow
-                 toFrame:(NSRect)newFrame
-{
-
-  GdkSurface *window = [[self contentView] gdkSurface];
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  gboolean maximized = gdk_surface_get_state (window) & GDK_SURFACE_STATE_MAXIMIZED;
-
-  if (maximized)
-    {
-      lastMaximizedFrame = newFrame;
-      gdk_synthesize_surface_state (window,
-                                   GDK_SURFACE_STATE_MAXIMIZED,
-                                   0);
-    }
-  else
-    {
-      lastUnmaximizedFrame = [nsWindow frame];
-      gdk_synthesize_surface_state (window,
-                                   0,
-                                   GDK_SURFACE_STATE_MAXIMIZED);
-    }
-
-  inMaximizeTransition = YES;
-  return YES;
-}
-
--(void)windowDidEndLiveResize:(NSNotification *)aNotification
-{
-  inMaximizeTransition = NO;
-}
-
--(NSSize)window:(NSWindow *)window willUseFullScreenContentSize:(NSSize)proposedSize
-{
-  return [[window screen] frame].size;
-}
-
--(void)windowWillEnterFullScreen:(NSNotification *)aNotification
-{
-  lastUnfullscreenFrame = [self frame];
-}
-
--(void)windowWillExitFullScreen:(NSNotification *)aNotification
-{
-  [self setFrame:lastUnfullscreenFrame display:YES];
-}
-
-@end
diff --git a/gdk/quartz/GdkQuartzNSWindow.h b/gdk/quartz/GdkQuartzNSWindow.h
deleted file mode 100644 (file)
index 2bf8b65..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/* GdkQuartzNSWindow.h
- *
- * Copyright (C) 2005-2007 Imendio AB
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#import <AppKit/AppKit.h>
-#import <Foundation/Foundation.h>
-#include <glib.h>
-#include <gdk.h>
-
-@interface GdkQuartzNSWindow : NSWindow {
-  BOOL    inMove;
-  BOOL    inShowOrHide;
-  BOOL    initialPositionKnown;
-
-  /* Manually triggered move/resize (not by the window manager) */
-  BOOL    inManualMove;
-  BOOL    inManualResize;
-  BOOL    inTrackManualResize;
-  NSPoint initialMoveLocation;
-  NSPoint initialResizeLocation;
-  NSRect  initialResizeFrame;
-  GdkSurfaceEdge resizeEdge;
-
-  NSRect  lastUnmaximizedFrame;
-  NSRect  lastMaximizedFrame;
-  NSRect  lastUnfullscreenFrame;
-  BOOL    inMaximizeTransition;
-}
-
--(BOOL)isInMove;
--(void)beginManualMove;
--(BOOL)trackManualMove;
--(BOOL)isInManualResizeOrMove;
--(void)beginManualResize:(GdkSurfaceEdge)edge;
--(BOOL)trackManualResize;
--(void)showAndMakeKey:(BOOL)makeKey;
--(void)hide;
-
-#ifdef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
--(void)setStyleMask:(NSUInteger)styleMask;
-#endif
-
-@end
-
-
-
-
diff --git a/gdk/quartz/GdkQuartzView.c b/gdk/quartz/GdkQuartzView.c
deleted file mode 100644 (file)
index 6e9a8a7..0000000
+++ /dev/null
@@ -1,712 +0,0 @@
-/* GdkQuartzView.m
- *
- * Copyright (C) 2005-2007 Imendio AB
- * Copyright (C) 2011 Hiroyuki Yamamoto
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#import "GdkQuartzView.h"
-#include "gdkquartzsurface.h"
-#include "gdkprivate-quartz.h"
-#include "gdkquartz.h"
-
-@implementation GdkQuartzView
-
--(id)initWithFrame: (NSRect)frameRect
-{
-  if ((self = [super initWithFrame: frameRect]))
-    {
-      markedRange = NSMakeRange (NSNotFound, 0);
-      selectedRange = NSMakeRange (NSNotFound, 0);
-    }
-
-  return self;
-}
-
--(BOOL)acceptsFirstResponder
-{
-  GDK_NOTE (EVENTS, g_message ("acceptsFirstResponder"));
-  return YES;
-}
-
--(BOOL)becomeFirstResponder
-{
-  GDK_NOTE (EVENTS, g_message ("becomeFirstResponder"));
-  return YES;
-}
-
--(BOOL)resignFirstResponder
-{
-  GDK_NOTE (EVENTS, g_message ("resignFirstResponder"));
-  return YES;
-}
-
--(void) keyDown: (NSEvent *) theEvent
-{
-  GDK_NOTE (EVENTS, g_message ("keyDown"));
-  [self interpretKeyEvents: [NSArray arrayWithObject: theEvent]];
-}
-
--(void)flagsChanged: (NSEvent *) theEvent
-{
-}
-
--(NSUInteger)characterIndexForPoint: (NSPoint)aPoint
-{
-  GDK_NOTE (EVENTS, g_message ("characterIndexForPoint"));
-  return 0;
-}
-
--(NSRect)firstRectForCharacterRange: (NSRange)aRange actualRange: (NSRangePointer)actualRange
-{
-  GDK_NOTE (EVENTS, g_message ("firstRectForCharacterRange"));
-  gint ns_x, ns_y;
-  GdkRectangle *rect;
-
-  rect = g_object_get_data (G_OBJECT (gdk_surface), GIC_CURSOR_RECT);
-  if (rect)
-    {
-      _gdk_quartz_surface_gdk_xy_to_xy (rect->x, rect->y + rect->height,
-                                      &ns_x, &ns_y);
-
-      return NSMakeRect (ns_x, ns_y, rect->width, rect->height);
-    }
-  else
-    {
-      return NSMakeRect (0, 0, 0, 0);
-    }
-}
-
--(NSArray *)validAttributesForMarkedText
-{
-  GDK_NOTE (EVENTS, g_message ("validAttributesForMarkedText"));
-  return [NSArray arrayWithObjects: NSUnderlineStyleAttributeName, nil];
-}
-
--(NSAttributedString *)attributedSubstringForProposedRange: (NSRange)aRange actualRange: (NSRangePointer)actualRange
-{
-  GDK_NOTE (EVENTS, g_message ("attributedSubstringForProposedRange"));
-  return nil;
-}
-
--(BOOL)hasMarkedText
-{
-  GDK_NOTE (EVENTS, g_message ("hasMarkedText"));
-  return markedRange.location != NSNotFound && markedRange.length != 0;
-}
-
--(NSRange)markedRange
-{
-  GDK_NOTE (EVENTS, g_message ("markedRange"));
-  return markedRange;
-}
-
--(NSRange)selectedRange
-{
-  GDK_NOTE (EVENTS, g_message ("selectedRange"));
-  return selectedRange;
-}
-
--(void)unmarkText
-{
-  GDK_NOTE (EVENTS, g_message ("unmarkText"));
-  gchar *prev_str;
-  markedRange = selectedRange = NSMakeRange (NSNotFound, 0);
-
-  g_object_set_data_full (G_OBJECT (gdk_surface), TIC_MARKED_TEXT, NULL, g_free);
-}
-
--(void)setMarkedText: (id)aString selectedRange: (NSRange)newSelection replacementRange: (NSRange)replacementRange
-{
-  GDK_NOTE (EVENTS, g_message ("setMarkedText"));
-  const char *str;
-  gchar *prev_str;
-
-  if (replacementRange.location == NSNotFound)
-    {
-      markedRange = NSMakeRange (newSelection.location, [aString length]);
-      selectedRange = NSMakeRange (newSelection.location, newSelection.length);
-    }
-  else {
-      markedRange = NSMakeRange (replacementRange.location, [aString length]);
-      selectedRange = NSMakeRange (replacementRange.location + newSelection.location, newSelection.length);
-    }
-
-  if ([aString isKindOfClass: [NSAttributedString class]])
-    {
-      str = [[aString string] UTF8String];
-    }
-  else {
-      str = [aString UTF8String];
-    }
-
-  g_object_set_data_full (G_OBJECT (gdk_surface), TIC_MARKED_TEXT, g_strdup (str), g_free);
-  g_object_set_data (G_OBJECT (gdk_surface), TIC_SELECTED_POS,
-                    GUINT_TO_POINTER (selectedRange.location));
-  g_object_set_data (G_OBJECT (gdk_surface), TIC_SELECTED_LEN,
-                    GUINT_TO_POINTER (selectedRange.length));
-
-  GDK_NOTE (EVENTS, g_message ("setMarkedText: set %s (%p, nsview %p): %s",
-                              TIC_MARKED_TEXT, gdk_surface, self,
-                              str ? str : "(empty)"));
-
-  /* handle text input changes by mouse events */
-  if (!GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (gdk_surface),
-                                            TIC_IN_KEY_DOWN)))
-    {
-      _gdk_quartz_synthesize_null_key_event(gdk_surface);
-    }
-}
-
--(void)doCommandBySelector: (SEL)aSelector
-{
-  GDK_NOTE (EVENTS, g_message ("doCommandBySelector"));
-  if ([self respondsToSelector: aSelector])
-    [self performSelector: aSelector];
-}
-
--(void)insertText: (id)aString replacementRange: (NSRange)replacementRange
-{
-  GDK_NOTE (EVENTS, g_message ("insertText"));
-  const char *str;
-  NSString *string;
-  gchar *prev_str;
-
-  if ([self hasMarkedText])
-    [self unmarkText];
-
-  if ([aString isKindOfClass: [NSAttributedString class]])
-      string = [aString string];
-  else
-      string = aString;
-
-  NSCharacterSet *ctrlChars = [NSCharacterSet controlCharacterSet];
-  NSCharacterSet *wsnlChars = [NSCharacterSet whitespaceAndNewlineCharacterSet];
-  if ([string rangeOfCharacterFromSet:ctrlChars].length &&
-      [string rangeOfCharacterFromSet:wsnlChars].length == 0)
-    {
-      /* discard invalid text input with Chinese input methods */
-      str = "";
-      [self unmarkText];
-      NSInputManager *currentInputManager = [NSInputManager currentInputManager];
-      [currentInputManager markedTextAbandoned:self];
-    }
-  else
-   {
-      str = [string UTF8String];
-   }
-
-  g_object_set_data_full (G_OBJECT (gdk_surface), TIC_INSERT_TEXT, g_strdup (str), g_free);
-  GDK_NOTE (EVENTS, g_message ("insertText: set %s (%p, nsview %p): %s",
-                            TIC_INSERT_TEXT, gdk_surface, self,
-                            str ? str : "(empty)"));
-
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_FILTERED));
-
-  /* handle text input changes by mouse events */
-  if (!GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (gdk_surface),
-                                            TIC_IN_KEY_DOWN)))
-    {
-      _gdk_quartz_synthesize_null_key_event(gdk_surface);
-    }
-}
-
--(void)deleteBackward: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("deleteBackward"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)deleteForward: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("deleteForward"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)deleteToBeginningOfLine: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("deleteToBeginningOfLine"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)deleteToEndOfLine: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("deleteToEndOfLine"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)deleteWordBackward: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("deleteWordBackward"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)deleteWordForward: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("deleteWordForward"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)insertBacktab: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("insertBacktab"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)insertNewline: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("insertNewline"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY, GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)insertTab: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("insertTab"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveBackward: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveBackward"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveBackwardAndModifySelection: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveBackwardAndModifySelection"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveDown: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveDown"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveDownAndModifySelection: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveDownAndModifySelection"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveForward: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveForward"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveForwardAndModifySelection: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveForwardAndModifySelection"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveLeft: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveLeft"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveLeftAndModifySelection: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveLeftAndModifySelection"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveRight: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveRight"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveRightAndModifySelection: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveRightAndModifySelection"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveToBeginningOfDocument: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveToBeginningOfDocument"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveToBeginningOfDocumentAndModifySelection: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveToBeginningOfDocumentAndModifySelection"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveToBeginningOfLine: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveToBeginningOfLine"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveToBeginningOfLineAndModifySelection: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveToBeginningOfLineAndModifySelection"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveToEndOfDocument: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveToEndOfDocument"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveToEndOfDocumentAndModifySelection: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveToEndOfDocumentAndModifySelection"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveToEndOfLine: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveToEndOfLine"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveToEndOfLineAndModifySelection: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveToEndOfLineAndModifySelection"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveUp: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveUp"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveUpAndModifySelection: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveUpAndModifySelection"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveWordBackward: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveWordBackward"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveWordBackwardAndModifySelection: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveWordBackwardAndModifySelection"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveWordForward: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveWordForward"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveWordForwardAndModifySelection: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveWordForwardAndModifySelection"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveWordLeft: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveWordLeft"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveWordLeftAndModifySelection: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveWordLeftAndModifySelection"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveWordRight: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveWordRight"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)moveWordRightAndModifySelection: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("moveWordRightAndModifySelection"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)pageDown: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("pageDown"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)pageDownAndModifySelection: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("pageDownAndModifySelection"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)pageUp: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("pageUp"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)pageUpAndModifySelection: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("pageUpAndModifySelection"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)selectAll: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("selectAll"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)selectLine: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("selectLine"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)selectWord: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("selectWord"));
-  g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
-                    GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
-}
-
--(void)noop: (id)sender
-{
-  GDK_NOTE (EVENTS, g_message ("noop"));
-}
-
-/* --------------------------------------------------------------- */
-
--(void)dealloc
-{
-  if (trackingRect)
-    {
-      [self removeTrackingRect: trackingRect];
-      trackingRect = 0;
-    }
-
-  [super dealloc];
-}
-
--(void)setGdkSurface: (GdkSurface *)window
-{
-  gdk_surface = window;
-}
-
--(GdkSurface *)gdkSurface
-{
-  return gdk_surface;
-}
-
--(NSTrackingRectTag)trackingRect
-{
-  return trackingRect;
-}
-
--(BOOL)isFlipped
-{
-  return YES;
-}
-
--(BOOL)isOpaque
-{
-  if (GDK_SURFACE_DESTROYED (gdk_surface))
-    return YES;
-
-  return NO;
-}
-
--(void)drawRect: (NSRect)rect
-{
-  GdkRectangle gdk_rect;
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (gdk_window->impl);
-  const NSRect *drawn_rects;
-  NSInteger count;
-  int i;
-  cairo_region_t *region;
-
-  if (GDK_SURFACE_DESTROYED (gdk_surface))
-    return;
-
-  if (! (gdk_window->event_mask & GDK_EXPOSURE_MASK))
-    return;
-
-  if (NSEqualRects (rect, NSZeroRect))
-    return;
-
-  if (!GDK_SURFACE_IS_MAPPED (gdk_surface))
-    {
-      /* If the window is not yet mapped, clip_region_with_children
-       * will be empty causing the usual code below to draw nothing.
-       * To not see garbage on the screen, we draw an aesthetic color
-       * here. The garbage would be visible if any widget enabled
-       * the NSView's CALayer in order to add sublayers for custom
-       * native rendering.
-       */
-      [NSGraphicsContext saveGraphicsState];
-
-      [[NSColor windowBackgroundColor] setFill];
-      [NSBezierPath fillRect: rect];
-
-      [NSGraphicsContext restoreGraphicsState];
-
-      return;
-    }
-
-  /* Clear our own bookkeeping of regions that need display */
-  if (impl->needs_display_region)
-    {
-      cairo_region_destroy (impl->needs_display_region);
-      impl->needs_display_region = NULL;
-    }
-
-  [self getRectsBeingDrawn: &drawn_rects count: &count];
-  region = cairo_region_create ();
-
-  for (i = 0; i < count; i++)
-    {
-      gdk_rect.x = drawn_rects[i].origin.x;
-      gdk_rect.y = drawn_rects[i].origin.y;
-      gdk_rect.width = drawn_rects[i].size.width;
-      gdk_rect.height = drawn_rects[i].size.height;
-
-      cairo_region_union_rectangle (region, &gdk_rect);
-    }
-
-  impl->in_paint_rect_count++;
-  _gdk_surface_process_updates_recurse (gdk_surface, region);
-  impl->in_paint_rect_count--;
-
-  cairo_region_destroy (region);
-
-  if (needsInvalidateShadow)
-    {
-      [[self window] invalidateShadow];
-      needsInvalidateShadow = NO;
-    }
-}
-
--(void)setNeedsInvalidateShadow: (BOOL)invalidate
-{
-  needsInvalidateShadow = invalidate;
-}
-
-/* For information on setting up tracking rects properly, see here:
- * http://developer.apple.com/documentation/Cocoa/Conceptual/EventOverview/EventOverview.pdf
- */
--(void)updateTrackingRect
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (gdk_window->impl);
-  NSRect rect;
-
-  if (!impl || !impl->toplevel)
-    return;
-
-  if (trackingRect)
-    {
-      [self removeTrackingRect: trackingRect];
-      trackingRect = 0;
-    }
-
-  if (!impl->toplevel)
-    return;
-
-  /* Note, if we want to set assumeInside we can use:
-   * NSPointInRect ([[self window] convertScreenToBase:[NSEvent mouseLocation]], rect)
-   */
-
-  rect = [self bounds];
-  trackingRect = [self addTrackingRect: rect
-                 owner: self
-                 userData: nil
-                 assumeInside: NO];
-}
-
--(void)viewDidMoveToWindow
-{
-  if (![self window]) /* We are destroyed already */
-    return;
-
-  [self updateTrackingRect];
-}
-
--(void)viewWillMoveToWindow: (NSWindow *)newWindow
-{
-  if (newWindow == nil && trackingRect)
-    {
-      [self removeTrackingRect: trackingRect];
-      trackingRect = 0;
-    }
-}
-
--(void)setFrame: (NSRect)frame
-{
-  [super setFrame: frame];
-
-  if ([self window])
-    [self updateTrackingRect];
-}
-
-@end
diff --git a/gdk/quartz/GdkQuartzView.h b/gdk/quartz/GdkQuartzView.h
deleted file mode 100644 (file)
index 24ce2fd..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/* GdkQuartzView.h
- *
- * Copyright (C) 2005 Imendio AB
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#import <AppKit/AppKit.h>
-#include "gdk/gdk.h"
-
-/* Text Input Client */
-#define TIC_MARKED_TEXT "tic-marked-text"
-#define TIC_SELECTED_POS  "tic-selected-pos"
-#define TIC_SELECTED_LEN  "tic-selected-len"
-#define TIC_INSERT_TEXT "tic-insert-text"
-#define TIC_IN_KEY_DOWN "tic-in-key-down"
-
-/* GtkIMContext */
-#define GIC_CURSOR_RECT  "gic-cursor-rect"
-#define GIC_FILTER_KEY   "gic-filter-key"
-#define GIC_FILTER_PASSTHRU    0
-#define GIC_FILTER_FILTERED    1
-
-@interface GdkQuartzView : NSView <NSTextInputClient>
-{
-  GdkSurface *gdk_surface;
-  NSTrackingRectTag trackingRect;
-  BOOL needsInvalidateShadow;
-  NSRange markedRange;
-  NSRange selectedRange;
-}
-
-- (void)setGdkSurface: (GdkSurface *)window;
-- (GdkSurface *)gdkSurface;
-- (NSTrackingRectTag)trackingRect;
-- (void)setNeedsInvalidateShadow: (BOOL)invalidate;
-
-@end
diff --git a/gdk/quartz/gdkcairocontext-quartz.c b/gdk/quartz/gdkcairocontext-quartz.c
deleted file mode 100644 (file)
index 2b23ab1..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* GDK - The GIMP Drawing Kit
- *
- * Copyright © 2018  Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include "gdkconfig.h"
-
-#include "gdkcairocontext-quartz.h"
-
-G_DEFINE_TYPE (GdkQuartzCairoContext, gdk_quartz_cairo_context, GDK_TYPE_CAIRO_CONTEXT)
-
-static void
-gdk_quartz_cairo_context_class_init (GdkQuartzCairoContextClass *klass)
-{
-}
-
-static void
-gdk_quartz_cairo_context_init (GdkQuartzCairoContext *self)
-{
-}
-
diff --git a/gdk/quartz/gdkcairocontext-quartz.h b/gdk/quartz/gdkcairocontext-quartz.h
deleted file mode 100644 (file)
index 98811b0..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/* GDK - The GIMP Drawing Kit
- *
- * Copyright © 2018  Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_CAIRO_CONTEXT__
-#define __GDK_QUARTZ_CAIRO_CONTEXT__
-
-#include "gdkconfig.h"
-
-#include "gdkcairocontextprivate.h"
-
-G_BEGIN_DECLS
-
-#define GDK_TYPE_QUARTZ_CAIRO_CONTEXT          (gdk_quartz_cairo_context_get_type ())
-#define GDK_QUARTZ_CAIRO_CONTEXT(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_QUARTZ_CAIRO_CONTEXT, GdkQuartzCairoContext))
-#define GDK_IS_QUARTZ_CAIRO_CONTEXT(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_QUARTZ_CAIRO_CONTEXT))
-#define GDK_QUARTZ_CAIRO_CONTEXT_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_QUARTZ_CAIRO_CONTEXT, GdkQuartzCairoContextClass))
-#define GDK_IS_QUARTZ_CAIRO_CONTEXT_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_QUARTZ_CAIRO_CONTEXT))
-#define GDK_QUARTZ_CAIRO_CONTEXT_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_QUARTZ_CAIRO_CONTEXT, GdkQuartzCairoContextClass))
-
-typedef struct _GdkQuartzCairoContext GdkQuartzCairoContext;
-typedef struct _GdkQuartzCairoContextClass GdkQuartzCairoContextClass;
-
-struct _GdkQuartzCairoContext
-{
-  GdkCairoContext parent_instance;
-};
-
-struct _GdkQuartzCairoContextClass
-{
-  GdkCairoContextClass parent_class;
-};
-
-GDK_AVAILABLE_IN_ALL
-GType gdk_quartz_cairo_context_get_type (void) G_GNUC_CONST;
-
-G_END_DECLS
-
-#endif /* __GDK_QUARTZ_CAIRO_CONTEXT__ */
diff --git a/gdk/quartz/gdkcursor-quartz.c b/gdk/quartz/gdkcursor-quartz.c
deleted file mode 100644 (file)
index 25e745d..0000000
+++ /dev/null
@@ -1,482 +0,0 @@
-/* gdkcursor-quartz.c
- *
- * Copyright (C) 2005-2007 Imendio AB
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include "gdkdisplay.h"
-#include "gdkcursor.h"
-#include "gdkcursorprivate.h"
-#include "gdkquartzcursor.h"
-#include "gdkprivate-quartz.h"
-
-#include "xcursors.h"
-
-struct _GdkQuartzCursor
-{
-  GdkCursor cursor;
-
-  NSCursor *nscursor;
-};
-
-struct _GdkQuartzCursorClass
-{
-  GdkCursorClass cursor_class;
-};
-
-
-static GdkCursor *cached_xcursors[G_N_ELEMENTS (xcursors)];
-
-static GdkCursor *
-gdk_quartz_cursor_new_from_nscursor (NSCursor      *nscursor,
-                                     GdkCursorType  cursor_type)
-{
-  GdkQuartzCursor *private;
-
-  private = g_object_new (GDK_TYPE_QUARTZ_CURSOR,
-                          "cursor-type", cursor_type,
-                          "display", _gdk_display,
-                          NULL);
-  private->nscursor = nscursor;
-
-  return GDK_CURSOR (private);
-}
-
-static GdkCursor *
-create_blank_cursor (void)
-{
-  NSCursor *nscursor;
-  NSImage *nsimage;
-  NSSize size = { 1.0, 1.0 };
-
-  nsimage = [[NSImage alloc] initWithSize:size];
-  nscursor = [[NSCursor alloc] initWithImage:nsimage
-                               hotSpot:NSMakePoint(0.0, 0.0)];
-  [nsimage release];
-
-  return gdk_quartz_cursor_new_from_nscursor (nscursor, GDK_BLANK_CURSOR);
-}
-
-static gboolean
-get_bit (const guchar *data,
-         gint          width,
-         gint          height,
-         gint          x,
-         gint          y)
-{
-  gint bytes_per_line;
-  const guchar *src;
-
-  if (x < 0 || y < 0 || x >= width || y >= height)
-    return FALSE;
-
-  bytes_per_line = (width + 7) / 8;
-
-  src = &data[y * bytes_per_line];
-  return ((src[x / 8] >> x % 8) & 1);
-}
-
-static GdkCursor *
-create_builtin_cursor (GdkCursorType cursor_type)
-{
-  GdkCursor *cursor;
-  NSBitmapImageRep *bitmap_rep;
-  NSInteger mask_width, mask_height;
-  gint src_width, src_height;
-  gint dst_stride;
-  const guchar *mask_start, *src_start;
-  gint dx, dy;
-  gint x, y;
-  NSPoint hotspot;
-  NSImage *image;
-  NSCursor *nscursor;
-
-  if (cursor_type >= G_N_ELEMENTS (xcursors) || cursor_type < 0)
-    return NULL;
-
-  cursor = cached_xcursors[cursor_type];
-  if (cursor)
-    return cursor;
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  src_width = xcursors[cursor_type].width;
-  src_height = xcursors[cursor_type].height;
-  mask_width = xcursors[cursor_type+1].width;
-  mask_height = xcursors[cursor_type+1].height;
-
-  bitmap_rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
-               pixelsWide:mask_width pixelsHigh:mask_height
-               bitsPerSample:8 samplesPerPixel:4
-               hasAlpha:YES isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace
-               bytesPerRow:0 bitsPerPixel:0];
-
-  dst_stride = [bitmap_rep bytesPerRow];
-
-  src_start = xcursors[cursor_type].bits;
-  mask_start = xcursors[cursor_type+1].bits;
-
-  dx = xcursors[cursor_type+1].hotx - xcursors[cursor_type].hotx;
-  dy = xcursors[cursor_type+1].hoty - xcursors[cursor_type].hoty;
-
-  for (y = 0; y < mask_height; y++)
-    {
-      guchar *dst = [bitmap_rep bitmapData] + y * dst_stride;
-
-      for (x = 0; x < mask_width; x++)
-       {
-         if (get_bit (mask_start, mask_width, mask_height, x, y))
-            {
-              if (get_bit (src_start, src_width, src_height, x - dx, y - dy))
-                {
-                  *dst++ = 0;
-                  *dst++ = 0;
-                  *dst++ = 0;
-                }
-              else
-                {
-                  *dst++ = 0xff;
-                  *dst++ = 0xff;
-                  *dst++ = 0xff;
-                }
-
-              *dst++ = 0xff;
-            }
-         else
-            {
-              *dst++ = 0;
-              *dst++ = 0;
-              *dst++ = 0;
-              *dst++ = 0;
-            }
-        }
-    }
-
-  image = [[NSImage alloc] init];
-  [image addRepresentation:bitmap_rep];
-  [bitmap_rep release];
-
-  hotspot = NSMakePoint (xcursors[cursor_type+1].hotx,
-                         xcursors[cursor_type+1].hoty);
-
-  nscursor = [[NSCursor alloc] initWithImage:image hotSpot:hotspot];
-  [image release];
-
-  cursor = gdk_quartz_cursor_new_from_nscursor (nscursor, GDK_CURSOR_IS_PIXMAP);
-
-  cached_xcursors[cursor_type] = g_object_ref (cursor);
-
-  GDK_QUARTZ_RELEASE_POOL;
-
-  return cursor;
-}
-
-GdkCursor*
-_gdk_quartz_display_get_cursor_for_type (GdkDisplay    *display,
-                                         GdkCursorType  cursor_type)
-{
-  NSCursor *nscursor;
-
-  g_return_val_if_fail (display == gdk_display_get_default (), NULL);
-
-  switch (cursor_type)
-    {
-    case GDK_XTERM:
-      nscursor = [NSCursor IBeamCursor];
-      break;
-    case GDK_SB_H_DOUBLE_ARROW:
-      nscursor = [NSCursor resizeLeftRightCursor];
-      break;
-    case GDK_SB_V_DOUBLE_ARROW:
-      nscursor = [NSCursor resizeUpDownCursor];
-      break;
-    case GDK_SB_UP_ARROW:
-    case GDK_BASED_ARROW_UP:
-    case GDK_BOTTOM_TEE:
-    case GDK_TOP_SIDE:
-      nscursor = [NSCursor resizeUpCursor];
-      break;
-    case GDK_SB_DOWN_ARROW:
-    case GDK_BASED_ARROW_DOWN:
-    case GDK_TOP_TEE:
-    case GDK_BOTTOM_SIDE:
-      nscursor = [NSCursor resizeDownCursor];
-      break;
-    case GDK_SB_LEFT_ARROW:
-    case GDK_RIGHT_TEE:
-    case GDK_LEFT_SIDE:
-      nscursor = [NSCursor resizeLeftCursor];
-      break;
-    case GDK_SB_RIGHT_ARROW:
-    case GDK_LEFT_TEE:
-    case GDK_RIGHT_SIDE:
-      nscursor = [NSCursor resizeRightCursor];
-      break;
-    case GDK_TCROSS:
-    case GDK_CROSS:
-    case GDK_CROSSHAIR:
-    case GDK_DIAMOND_CROSS:
-      nscursor = [NSCursor crosshairCursor];
-      break;
-    case GDK_HAND1:
-    case GDK_HAND2:
-      nscursor = [NSCursor pointingHandCursor];
-      break;
-    case GDK_CURSOR_IS_PIXMAP:
-      return NULL;
-    case GDK_BLANK_CURSOR:
-      return create_blank_cursor ();
-    default:
-      return g_object_ref (create_builtin_cursor (cursor_type));
-    }
-
-  [nscursor retain];
-  return gdk_quartz_cursor_new_from_nscursor (nscursor, cursor_type);
-}
-
-
-GdkCursor *
-_gdk_quartz_display_get_cursor_for_surface (GdkDisplay      *display,
-                                           cairo_surface_t *surface,
-                                           gdouble          x,
-                                           gdouble          y)
-{
-  NSImage *image;
-  NSCursor *nscursor;
-  GdkCursor *cursor;
-  GdkPixbuf *pixbuf;
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0,
-                                       cairo_image_surface_get_width (surface),
-                                       cairo_image_surface_get_height (surface));
-  image = gdk_quartz_pixbuf_to_ns_image_libgtk_only (pixbuf);
-  nscursor = [[NSCursor alloc] initWithImage:image hotSpot:NSMakePoint(x, y)];
-
-  cursor = gdk_quartz_cursor_new_from_nscursor (nscursor, GDK_CURSOR_IS_PIXMAP);
-
-  g_object_unref (pixbuf);
-
-  GDK_QUARTZ_RELEASE_POOL;
-
-  return cursor;
-}
-
-/* OS X only exports a number of cursor types in its public NSCursor interface.
- * By overriding the private _coreCursorType method, we can tell OS X to load
- * one of its internal cursors instead (since cursor images are loaded on demand
- * instead of in advance). WebKit does this too.
- */
-
-@interface gdkCoreCursor : NSCursor {
-@private
-       int type;
-       BOOL override;
-}
-@end
-
-@implementation gdkCoreCursor
-
-- (int)_coreCursorType
-{
-       if (self->override)
-               return self->type;
-       return [super _coreCursorType];
-}
-
-#define CUSTOM_CURSOR_CTOR(name, id) \
-       + (gdkCoreCursor *)name \
-       { \
-               gdkCoreCursor *obj; \
-               obj = [self new]; \
-               if (obj) { \
-                       obj->override = YES; \
-                       obj->type = id; \
-               } \
-               return obj; \
-       }
-CUSTOM_CURSOR_CTOR(gdkHelpCursor, 40)
-CUSTOM_CURSOR_CTOR(gdkProgressCursor, 4)
-/* TODO OS X doesn't seem to have a way to get this. There is an undocumented
- * method +[NSCursor _waitCursor], but it doesn't actually return this cursor,
- * but rather some odd low-quality non-animating version of this cursor. Use
- * the progress cursor instead for now.
- */
-CUSTOM_CURSOR_CTOR(gdkWaitCursor, 4)
-CUSTOM_CURSOR_CTOR(gdkAliasCursor, 2)
-CUSTOM_CURSOR_CTOR(gdkMoveCursor, 39)
-/* TODO OS X doesn't seem to provide one; copy the move cursor for now
- *  since it looks similar to what we want. */
-CUSTOM_CURSOR_CTOR(gdkAllScrollCursor, 39)
-CUSTOM_CURSOR_CTOR(gdkNEResizeCursor, 29)
-CUSTOM_CURSOR_CTOR(gdkNWResizeCursor, 33)
-CUSTOM_CURSOR_CTOR(gdkSEResizeCursor, 35)
-CUSTOM_CURSOR_CTOR(gdkSWResizeCursor, 37)
-CUSTOM_CURSOR_CTOR(gdkEWResizeCursor, 28)
-CUSTOM_CURSOR_CTOR(gdkNSResizeCursor, 32)
-CUSTOM_CURSOR_CTOR(gdkNESWResizeCursor, 30)
-CUSTOM_CURSOR_CTOR(gdkNWSEResizeCursor, 34)
-CUSTOM_CURSOR_CTOR(gdkZoomInCursor, 42)
-CUSTOM_CURSOR_CTOR(gdkZoomOutCursor, 43)
-
-@end
-
-struct CursorsByName {
-  const gchar *name;
-  NSString *selector;
-};
-
-static const struct CursorsByName cursors_by_name[] = {
-  /* Link & Status */
-  { "context-menu", @"contextualMenuCursor" },
-  { "help", @"gdkHelpCursor" },
-  { "pointer", @"pointingHandCursor" },
-  { "progress", @"gdkProgressCursor" },
-  { "wait", @"gdkWaitCursor" },
-  /* Selection */
-  { "cell", @"crosshairCursor" },
-  { "crosshair", @"crosshairCursor" },
-  { "text", @"IBeamCursor" },
-  { "vertical-text", @"IBeamCursorForVerticalLayout" },
-  /* Drag & Drop */
-  { "alias", @"gdkAliasCursor" },
-  { "copy", @"dragCopyCursor" },
-  { "move", @"gdkMoveCursor" },
-  { "no-drop", @"operationNotAllowedCursor" },
-  { "not-allowed", @"operationNotAllowedCursor" },
-  { "grab", @"openHandCursor" },
-  { "grabbing", @"closedHandCursor" },
-  /* Resize & Scrolling */
-  { "all-scroll", @"gdkAllScrollCursor" },
-  { "col-resize", @"resizeLeftRightCursor" },
-  { "row-resize", @"resizeUpDownCursor" },
-  { "n-resize", @"resizeUpCursor" },
-  { "e-resize", @"resizeRightCursor" },
-  { "s-resize", @"resizeDownCursor" },
-  { "w-resize", @"resizeLeftCursor" },
-  { "ne-resize", @"gdkNEResizeCursor" },
-  { "nw-resize", @"gdkNWResizeCursor" },
-  { "se-resize", @"gdkSEResizeCursor" },
-  { "sw-resize", @"gdkSWResizeCursor" },
-  { "ew-resize", @"gdkEWResizeCursor" },
-  { "ns-resize", @"gdkNSResizeCursor" },
-  { "nesw-resize", @"gdkNESWResizeCursor" },
-  { "nwse-resize", @"gdkNWSEResizeCursor" },
-  /* Zoom */
-  { "zoom-in", @"gdkZoomInCursor" },
-  { "zoom-out", @"gdkZoomOutCursor" },
-  { NULL, NULL },
-};
-
-GdkCursor*
-_gdk_quartz_display_get_cursor_for_name (GdkDisplay  *display,
-                                         const gchar *name)
-{
-  NSCursor *nscursor;
-  const struct CursorsByName *test;
-  SEL selector;
-
-  if (name == NULL || g_str_equal (name, "none"))
-    return create_blank_cursor ();
-
-  // use this selector if nothing found
-  selector = @selector(arrowCursor);
-  for (test = cursors_by_name; test->name != NULL; test++)
-    if (g_str_equal (name, test->name))
-      {
-        selector = NSSelectorFromString(test->selector);
-        break;
-      }
-  nscursor = [[gdkCoreCursor class] performSelector:selector];
-
-  [nscursor retain];
-  return gdk_quartz_cursor_new_from_nscursor (nscursor, GDK_CURSOR_IS_PIXMAP);
-}
-
-G_DEFINE_TYPE (GdkQuartzCursor, gdk_quartz_cursor, GDK_TYPE_CURSOR)
-
-static void
-gdk_quartz_cursor_finalize (GObject *object)
-{
-  GdkQuartzCursor *private = GDK_QUARTZ_CURSOR (object);
-
-  if (private->nscursor)
-    [private->nscursor release];
-  private->nscursor = NULL;
-}
-
-static void
-gdk_quartz_cursor_class_init (GdkQuartzCursorClass *quartz_cursor_class)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (quartz_cursor_class);
-
-  object_class->finalize = gdk_quartz_cursor_finalize;
-}
-
-static void
-gdk_quartz_cursor_init (GdkQuartzCursor *cursor)
-{
-}
-
-
-gboolean
-_gdk_quartz_display_supports_cursor_alpha (GdkDisplay *display)
-{
-  return TRUE;
-}
-
-gboolean
-_gdk_quartz_display_supports_cursor_color (GdkDisplay *display)
-{
-  return TRUE;
-}
-
-void
-_gdk_quartz_display_get_default_cursor_size (GdkDisplay *display,
-                                             guint      *width,
-                                             guint      *height)
-{
-  /* Mac OS X doesn't have the notion of a default size */
-  *width = 32;
-  *height = 32;
-}
-
-void
-_gdk_quartz_display_get_maximal_cursor_size (GdkDisplay *display,
-                                             guint       *width,
-                                             guint       *height)
-{
-  /* Cursor sizes in Mac OS X can be arbitrarily large */
-  *width = 65536;
-  *height = 65536;
-}
-
-NSCursor *
-_gdk_quartz_cursor_get_ns_cursor (GdkCursor *cursor)
-{
-  GdkQuartzCursor *cursor_private;
-
-  if (!cursor)
-    return [NSCursor arrowCursor];
-
-  g_return_val_if_fail (GDK_IS_QUARTZ_CURSOR (cursor), NULL);
-
-  cursor_private = GDK_QUARTZ_CURSOR (cursor);
-
-  return cursor_private->nscursor;
-}
diff --git a/gdk/quartz/gdkdevice-core-quartz.c b/gdk/quartz/gdkdevice-core-quartz.c
deleted file mode 100644 (file)
index 2d6233e..0000000
+++ /dev/null
@@ -1,347 +0,0 @@
-/* GDK - The GIMP Drawing Kit
- * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
- * Copyright (C) 2010 Kristian Rietveld <kris@gtk.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include <gdk/gdkdeviceprivate.h>
-#include <gdk/gdkdisplayprivate.h>
-
-#import "GdkQuartzView.h"
-#include "gdkquartzsurface.h"
-#include "gdkquartzcursor.h"
-#include "gdkprivate-quartz.h"
-#include "gdkquartzdevice-core.h"
-
-struct _GdkQuartzDeviceCore
-{
-  GdkDevice parent_instance;
-};
-
-struct _GdkQuartzDeviceCoreClass
-{
-  GdkDeviceClass parent_class;
-};
-
-static gboolean gdk_quartz_device_core_get_history (GdkDevice      *device,
-                                                    GdkSurface      *window,
-                                                    guint32         start,
-                                                    guint32         stop,
-                                                    GdkTimeCoord ***events,
-                                                    gint           *n_events);
-static void gdk_quartz_device_core_get_state (GdkDevice       *device,
-                                              GdkSurface       *window,
-                                              gdouble         *axes,
-                                              GdkModifierType *mask);
-static void gdk_quartz_device_core_set_surface_cursor (GdkDevice *device,
-                                                      GdkSurface *window,
-                                                      GdkCursor *cursor);
-static void gdk_quartz_device_core_warp (GdkDevice *device,
-                                         gdouble    x,
-                                         gdouble    y);
-static void gdk_quartz_device_core_query_state (GdkDevice        *device,
-                                                GdkSurface        *window,
-                                                GdkSurface       **root_window,
-                                                GdkSurface       **child_window,
-                                                gdouble          *root_x,
-                                                gdouble          *root_y,
-                                                gdouble          *win_x,
-                                                gdouble          *win_y,
-                                                GdkModifierType  *mask);
-static GdkGrabStatus gdk_quartz_device_core_grab   (GdkDevice     *device,
-                                                    GdkSurface     *window,
-                                                    gboolean       owner_events,
-                                                    GdkEventMask   event_mask,
-                                                    GdkSurface     *confine_to,
-                                                    GdkCursor     *cursor,
-                                                    guint32        time_);
-static void          gdk_quartz_device_core_ungrab (GdkDevice     *device,
-                                                    guint32        time_);
-static GdkSurface * gdk_quartz_device_core_surface_at_position (GdkDevice       *device,
-                                                              gdouble         *win_x,
-                                                              gdouble         *win_y,
-                                                              GdkModifierType *mask,
-                                                              gboolean         get_toplevel);
-
-
-G_DEFINE_TYPE (GdkQuartzDeviceCore, gdk_quartz_device_core, GDK_TYPE_DEVICE)
-
-static void
-gdk_quartz_device_core_class_init (GdkQuartzDeviceCoreClass *klass)
-{
-  GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
-
-  device_class->get_history = gdk_quartz_device_core_get_history;
-  device_class->get_state = gdk_quartz_device_core_get_state;
-  device_class->set_surface_cursor = gdk_quartz_device_core_set_surface_cursor;
-  device_class->warp = gdk_quartz_device_core_warp;
-  device_class->query_state = gdk_quartz_device_core_query_state;
-  device_class->grab = gdk_quartz_device_core_grab;
-  device_class->ungrab = gdk_quartz_device_core_ungrab;
-  device_class->surface_at_position = gdk_quartz_device_core_surface_at_position;
-}
-
-static void
-gdk_quartz_device_core_init (GdkQuartzDeviceCore *quartz_device_core)
-{
-  GdkDevice *device;
-
-  device = GDK_DEVICE (quartz_device_core);
-
-  _gdk_device_add_axis (device, NULL, GDK_AXIS_X, 0, 0, 1);
-  _gdk_device_add_axis (device, NULL, GDK_AXIS_Y, 0, 0, 1);
-}
-
-static gboolean
-gdk_quartz_device_core_get_history (GdkDevice      *device,
-                                    GdkSurface      *window,
-                                    guint32         start,
-                                    guint32         stop,
-                                    GdkTimeCoord ***events,
-                                    gint           *n_events)
-{
-  return FALSE;
-}
-
-static void
-gdk_quartz_device_core_get_state (GdkDevice       *device,
-                                  GdkSurface       *window,
-                                  gdouble         *axes,
-                                  GdkModifierType *mask)
-{
-  gdouble x_pos, y_pos;
-
-  gdk_surface_get_device_position (window, device, &x_pos, &y_pos, mask);
-
-  if (axes)
-    {
-      axes[0] = x_pos;
-      axes[1] = y_pos;
-    }
-}
-
-static void
-translate_coords_to_child_coords (GdkSurface *parent,
-                                  GdkSurface *child,
-                                  gint      *x,
-                                  gint      *y)
-{
-  GdkSurface *current = child;
-
-  if (child == parent)
-    return;
-
-  while (current != parent)
-    {
-      gint tmp_x, tmp_y;
-
-      gdk_surface_get_origin (current, &tmp_x, &tmp_y);
-
-      *x -= tmp_x;
-      *y -= tmp_y;
-
-      current = gdk_surface_get_parent (current);
-    }
-}
-
-static void
-gdk_quartz_device_core_set_surface_cursor (GdkDevice *device,
-                                          GdkSurface *window,
-                                          GdkCursor *cursor)
-{
-  NSCursor *nscursor;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  nscursor = _gdk_quartz_cursor_get_ns_cursor (cursor);
-
-  [nscursor set];
-}
-
-static void
-gdk_quartz_device_core_warp (GdkDevice *device,
-                             gdouble    x,
-                             gdouble    y)
-{
-  CGDisplayMoveCursorToPoint (CGMainDisplayID (), CGPointMake (x, y));
-}
-
-static GdkSurface *
-gdk_quartz_device_core_query_state_helper (GdkSurface       *window,
-                                           GdkDevice       *device,
-                                           gdouble         *x,
-                                           gdouble         *y,
-                                           GdkModifierType *mask)
-{
-  GdkSurface *toplevel;
-  NSPoint point;
-  gint x_tmp, y_tmp;
-  GdkSurface *found_window;
-
-  g_return_val_if_fail (window == NULL || GDK_IS_SURFACE (window), NULL);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    {
-      *x = 0;
-      *y = 0;
-      *mask = 0;
-      return NULL;
-    }
-
-  toplevel = gdk_surface_get_toplevel (window);
-
-  if (mask)
-    *mask = _gdk_quartz_events_get_current_keyboard_modifiers () |
-        _gdk_quartz_events_get_current_mouse_modifiers ();
-
-  /* Get the y coordinate, needs to be flipped. */
-  if (window == _gdk_root)
-    {
-      point = [NSEvent mouseLocation];
-      _gdk_quartz_surface_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
-    }
-  else
-    {
-      GdkSurfaceImplQuartz *impl;
-      NSWindow *nswindow;
-
-      impl = GDK_SURFACE_IMPL_QUARTZ (toplevel->impl);
-      nswindow = impl->toplevel;
-
-      point = [nswindow mouseLocationOutsideOfEventStream];
-
-      x_tmp = point.x;
-      y_tmp = toplevel->height - point.y;
-
-      window = toplevel;
-    }
-
-  found_window = _gdk_quartz_surface_find_child (window, x_tmp, y_tmp,
-                                                FALSE);
-
-  if (found_window == _gdk_root)
-    found_window = NULL;
-  else if (found_window)
-    translate_coords_to_child_coords (window, found_window,
-                                      &x_tmp, &y_tmp);
-
-  if (x)
-    *x = x_tmp;
-
-  if (y)
-    *y = y_tmp;
-
-  return found_window;
-}
-
-static void
-gdk_quartz_device_core_query_state (GdkDevice        *device,
-                                    GdkSurface        *window,
-                                    GdkSurface       **child_window,
-                                    gdouble          *root_x,
-                                    gdouble          *root_y,
-                                    gdouble          *win_x,
-                                    gdouble          *win_y,
-                                    GdkModifierType  *mask)
-{
-  GdkSurface *found_window;
-  NSPoint point;
-  gint x_tmp, y_tmp;
-
-  if (window == NULL)
-    window = _gdk_root;
-
-  found_window = gdk_quartz_device_core_query_state_helper (window, device,
-                                                            win_x, win_y,
-                                                            mask);
-
-  if (root_window)
-    *root_window = _gdk_root;
-
-  if (child_window)
-    *child_window = found_window;
-
-  point = [NSEvent mouseLocation];
-  _gdk_quartz_surface_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
-
-  if (root_x)
-    *root_x = x_tmp;
-
-  if (root_y)
-    *root_y = y_tmp;
-}
-
-static GdkGrabStatus
-gdk_quartz_device_core_grab (GdkDevice    *device,
-                             GdkSurface    *window,
-                             gboolean      owner_events,
-                             GdkEventMask  event_mask,
-                             GdkSurface    *confine_to,
-                             GdkCursor    *cursor,
-                             guint32       time_)
-{
-  /* Should remain empty */
-  return GDK_GRAB_SUCCESS;
-}
-
-static void
-gdk_quartz_device_core_ungrab (GdkDevice *device,
-                               guint32    time_)
-{
-  GdkDeviceGrabInfo *grab;
-
-  grab = _gdk_display_get_last_device_grab (_gdk_display, device);
-  if (grab)
-    grab->serial_end = 0;
-
-  _gdk_display_device_grab_update (_gdk_display, device, NULL, 0);
-}
-
-static GdkSurface *
-gdk_quartz_device_core_surface_at_position (GdkDevice       *device,
-                                           gdouble         *win_x,
-                                           gdouble         *win_y,
-                                           GdkModifierType *mask,
-                                           gboolean         get_toplevel)
-{
-  GdkSurface *found_window;
-  NSPoint point;
-  gint x_tmp, y_tmp;
-
-  /* Get mouse coordinates, find window under the mouse pointer */
-  point = [NSEvent mouseLocation];
-  _gdk_quartz_surface_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
-
-  found_window = _gdk_quartz_surface_find_child (_gdk_root, x_tmp, y_tmp, get_toplevel);
-
-  if (found_window)
-    translate_coords_to_child_coords (_gdk_root, found_window, &x_tmp, &y_tmp);
-
-  if (win_x)
-    *win_x = found_window ? x_tmp : -1;
-
-  if (win_y)
-    *win_y = found_window ? y_tmp : -1;
-
-  if (mask)
-    *mask = _gdk_quartz_events_get_current_keyboard_modifiers () |
-        _gdk_quartz_events_get_current_mouse_modifiers ();
-
-  return found_window;
-}
-
diff --git a/gdk/quartz/gdkdevicemanager-core-quartz.c b/gdk/quartz/gdkdevicemanager-core-quartz.c
deleted file mode 100644 (file)
index 9e4620c..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/* GDK - The GIMP Drawing Kit
- * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include <gdk/gdktypes.h>
-#include <gdk/gdkdevicemanager.h>
-#include <gdk/gdkdeviceprivate.h>
-#include <gdk/gdkseatdefaultprivate.h>
-#include <gdk/gdkdevicemanagerprivate.h>
-#include "gdkdevicemanager-core-quartz.h"
-#include "gdkquartzdevice-core.h"
-#include "gdkkeysyms.h"
-#include "gdkprivate-quartz.h"
-
-
-#define HAS_FOCUS(toplevel)                           \
-  ((toplevel)->has_focus || (toplevel)->has_pointer_focus)
-
-static void    gdk_quartz_device_manager_core_finalize    (GObject *object);
-static void    gdk_quartz_device_manager_core_constructed (GObject *object);
-
-static GdkDevice * gdk_quartz_device_manager_core_get_client_pointer (GdkDeviceManager *device_manager);
-
-
-G_DEFINE_TYPE (GdkQuartzDeviceManagerCore, gdk_quartz_device_manager_core, G_TYPE_OBJECT)
-
-static void
-gdk_quartz_device_manager_core_class_init (GdkQuartzDeviceManagerCoreClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-  object_class->finalize = gdk_quartz_device_manager_core_finalize;
-  object_class->constructed = gdk_quartz_device_manager_core_constructed;
-}
-
-static GdkDevice *
-create_core_pointer (GdkQuartzDeviceManagerCore *device_manager,
-                     GdkDisplay                 *display)
-{
-  return g_object_new (GDK_TYPE_QUARTZ_DEVICE_CORE,
-                       "name", "Core Pointer",
-                       "type", GDK_DEVICE_TYPE_LOGICAL,
-                       "input-source", GDK_SOURCE_MOUSE,
-                       "input-mode", GDK_MODE_SCREEN,
-                       "has-cursor", TRUE,
-                       "display", display,
-                       "device-manager", device_manager,
-                       NULL);
-}
-
-static GdkDevice *
-create_core_keyboard (GdkQuartzDeviceManagerCore *device_manager,
-                      GdkDisplay                 *display)
-{
-  return g_object_new (GDK_TYPE_QUARTZ_DEVICE_CORE,
-                       "name", "Core Keyboard",
-                       "type", GDK_DEVICE_TYPE_LOGICAL,
-                       "input-source", GDK_SOURCE_KEYBOARD,
-                       "input-mode", GDK_MODE_SCREEN,
-                       "has-cursor", FALSE,
-                       "display", display,
-                       "device-manager", device_manager,
-                       NULL);
-}
-
-static void
-gdk_quartz_device_manager_core_init (GdkQuartzDeviceManagerCore *device_manager)
-{
-}
-
-static void
-gdk_quartz_device_manager_core_finalize (GObject *object)
-{
-  GdkQuartzDeviceManagerCore *quartz_device_manager_core;
-
-  quartz_device_manager_core = GDK_QUARTZ_DEVICE_MANAGER_CORE (object);
-
-  g_object_unref (quartz_device_manager_core->core_pointer);
-  g_object_unref (quartz_device_manager_core->core_keyboard);
-
-  G_OBJECT_CLASS (gdk_quartz_device_manager_core_parent_class)->finalize (object);
-}
-
-static void
-gdk_quartz_device_manager_core_constructed (GObject *object)
-{
-  GdkQuartzDeviceManagerCore *device_manager;
-  GdkDisplay *display;
-  GdkSeat *seat;
-
-  display = _gdk_display;
-
-  device_manager = GDK_QUARTZ_DEVICE_MANAGER_CORE (object);
-  device_manager->core_pointer = create_core_pointer (GDK_DEVICE_MANAGER (device_manager), display);
-  device_manager->core_keyboard = create_core_keyboard (GDK_DEVICE_MANAGER (device_manager), display);
-
-  _gdk_device_set_associated_device (device_manager->core_pointer, device_manager->core_keyboard);
-  _gdk_device_set_associated_device (device_manager->core_keyboard, device_manager->core_pointer);
-
-  seat = gdk_seat_default_new_for_logical_pair (device_manager->core_pointer,
-                                                device_manager->core_keyboard);
-  gdk_display_add_seat (display, seat);
-  g_object_unref (seat);
-}
diff --git a/gdk/quartz/gdkdevicemanager-core-quartz.h b/gdk/quartz/gdkdevicemanager-core-quartz.h
deleted file mode 100644 (file)
index 178e97c..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/* gdkdevicemanager-quartz.h
- *
- * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
- * Copyright (C) 2010  Kristian Rietveld  <kris@gtk.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_DEVICE_MANAGER_CORE__
-#define __GDK_QUARTZ_DEVICE_MANAGER_CORE__
-
-#include <gdkdevicemanagerprivate.h>
-#include "gdkquartzdevicemanager-core.h"
-
-G_BEGIN_DECLS
-
-struct _GdkQuartzDeviceManagerCore
-{
-  GObject parent_object;
-  GdkDevice *core_pointer;
-  GdkDevice *core_keyboard;
-};
-
-struct _GdkQuartzDeviceManagerCoreClass
-{
-  GObjectClass parent_class;
-};
-
-G_END_DECLS
-
-#endif /* __GDK_QUARTZ_DEVICE_MANAGER__ */
diff --git a/gdk/quartz/gdkdisplay-quartz.c b/gdk/quartz/gdkdisplay-quartz.c
deleted file mode 100644 (file)
index 300d9d8..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/* gdkdisplay-quartz.c
- *
- * Copyright (C) 2005 Imendio AB
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include <gdk/gdk.h>
-#include <gdk/gdkdisplayprivate.h>
-
-#include "gdkprivate-quartz.h"
-#include "gdkquartzscreen.h"
-#include "gdkquartzsurface.h"
-#include "gdkquartzdisplay.h"
-#include "gdkquartzdevicemanager-core.h"
-#include "gdkmonitorprivate.h"
-#include "gdkdisplay-quartz.h"
-#include "gdkcairocontext-quartz.h"
-
-
-static GdkSurface *
-gdk_quartz_display_get_default_group (GdkDisplay *display)
-{
-  g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
-
-  /* FIXME: Implement */
-
-  return NULL;
-}
-
-GdkDeviceManager *
-_gdk_device_manager_new (GdkDisplay *display)
-{
-  return g_object_new (GDK_TYPE_QUARTZ_DEVICE_MANAGER_CORE,
-                       "display", display,
-                       NULL);
-}
-
-GdkDisplay *
-_gdk_quartz_display_open (const gchar *display_name)
-{
-  if (_gdk_display != NULL)
-    return NULL;
-
-  _gdk_display = g_object_new (gdk_quartz_display_get_type (), NULL);
-  _gdk_device_manager = _gdk_device_manager_new (_gdk_display);
-
-  _gdk_screen = g_object_new (gdk_quartz_screen_get_type (), NULL);
-
-  _gdk_quartz_surface_init_windowing (_gdk_display);
-
-  _gdk_quartz_events_init ();
-
-  /* Initialize application */
-  [NSApplication sharedApplication];
-#if 0
-  /* FIXME: Remove the #if 0 when we have these functions */
-  _gdk_quartz_dnd_init ();
-#endif
-
-  g_signal_emit_by_name (_gdk_display, "opened");
-
-  return _gdk_display;
-}
-
-static const gchar *
-gdk_quartz_display_get_name (GdkDisplay *display)
-{
-  static gchar *display_name = NULL;
-
-  if (!display_name)
-    {
-      GDK_QUARTZ_ALLOC_POOL;
-      display_name = g_strdup ([[[NSHost currentHost] name] UTF8String]);
-      GDK_QUARTZ_RELEASE_POOL;
-    }
-
-  return display_name;
-}
-
-static void
-gdk_quartz_display_beep (GdkDisplay *display)
-{
-  g_return_if_fail (GDK_IS_DISPLAY (display));
-
-  NSBeep();
-}
-
-static void
-gdk_quartz_display_sync (GdkDisplay *display)
-{
-  /* Not supported. */
-}
-
-static void
-gdk_quartz_display_flush (GdkDisplay *display)
-{
-  /* Not supported. */
-}
-
-static gboolean
-gdk_quartz_display_supports_shapes (GdkDisplay *display)
-{
-  /* FIXME: Implement */
-  return FALSE;
-}
-
-static gboolean
-gdk_quartz_display_supports_input_shapes (GdkDisplay *display)
-{
-  /* FIXME: Implement */
-  return FALSE;
-}
-
-static gulong
-gdk_quartz_display_get_next_serial (GdkDisplay *display)
-{
-  return 0;
-}
-
-static void
-gdk_quartz_display_notify_startup_complete (GdkDisplay  *display,
-                                            const gchar *startup_id)
-{
-  /* FIXME: Implement? */
-}
-
-static int
-gdk_quartz_display_get_n_monitors (GdkDisplay *display)
-{
-  GdkQuartzDisplay *quartz_display = GDK_QUARTZ_DISPLAY (display);
-
-  return quartz_display->monitors->len;
-}
-
-
-static GdkMonitor *
-gdk_quartz_display_get_monitor (GdkDisplay *display,
-                                int         monitor_num)
-{
-  GdkQuartzDisplay *quartz_display = GDK_QUARTZ_DISPLAY (display);
-
-  if (0 <= monitor_num || monitor_num < quartz_display->monitors->len)
-    return (GdkMonitor *)quartz_display->monitors->pdata[monitor_num];
-
-  return NULL;
-}
-
-static gboolean
-gdk_quartz_display_get_setting (GdkDisplay  *display,
-                                const gchar *name,
-                                GValue      *value)
-{
-  return _gdk_quartz_get_setting (name, value);
-}
-
-
-G_DEFINE_TYPE (GdkQuartzDisplay, gdk_quartz_display, GDK_TYPE_DISPLAY)
-
-static void
-gdk_quartz_display_init (GdkQuartzDisplay *display)
-{
-  GDK_QUARTZ_ALLOC_POOL;
-
-  display->monitors = g_ptr_array_new_with_free_func (g_object_unref);
-
-  GDK_QUARTZ_RELEASE_POOL;
-}
-
-static void
-gdk_quartz_display_dispose (GObject *object)
-{
-  GdkQuartzDisplay *display_quartz = GDK_QUARTZ_DISPLAY (object);
-
-  g_ptr_array_free (display_quartz->monitors, TRUE);
-
-  G_OBJECT_CLASS (gdk_quartz_display_parent_class)->dispose (object);
-}
-
-static void
-gdk_quartz_display_finalize (GObject *object)
-{
-  GdkQuartzDisplay *display_quartz = GDK_QUARTZ_DISPLAY (object);
-
-  G_OBJECT_CLASS (gdk_quartz_display_parent_class)->finalize (object);
-}
-
-static void
-gdk_quartz_display_class_init (GdkQuartzDisplayClass *class)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (class);
-  GdkDisplayClass *display_class = GDK_DISPLAY_CLASS (class);
-
-  object_class->finalize = gdk_quartz_display_finalize;
-  object_class->dispose = gdk_quartz_display_dispose;
-
-  display_class->surface_type = GDK_TYPE_QUARTZ_SURFACE;
-  display_class->cairo_context_type = GDK_TYPE_QUARTZ_CAIRO_CONTEXT;
-
-  display_class->get_name = gdk_quartz_display_get_name;
-  display_class->beep = gdk_quartz_display_beep;
-  display_class->sync = gdk_quartz_display_sync;
-  display_class->flush = gdk_quartz_display_flush;
-  display_class->queue_events = _gdk_quartz_display_queue_events;
-  display_class->has_pending = _gdk_quartz_display_has_pending;
-  display_class->get_default_group = gdk_quartz_display_get_default_group;
-  display_class->supports_shapes = gdk_quartz_display_supports_shapes;
-  display_class->supports_input_shapes = gdk_quartz_display_supports_input_shapes;
-  display_class->get_default_cursor_size = _gdk_quartz_display_get_default_cursor_size;
-  display_class->get_maximal_cursor_size = _gdk_quartz_display_get_maximal_cursor_size;
-  display_class->supports_cursor_alpha = _gdk_quartz_display_supports_cursor_alpha;
-  display_class->supports_cursor_color = _gdk_quartz_display_supports_cursor_color;
-
-  display_class->get_next_serial = gdk_quartz_display_get_next_serial;
-  display_class->notify_startup_complete = gdk_quartz_display_notify_startup_complete;
-  display_class->event_data_copy = _gdk_quartz_display_event_data_copy;
-  display_class->event_data_free = _gdk_quartz_display_event_data_free;
-  display_class->create_surface_impl = _gdk_quartz_display_create_surface_impl;
-  display_class->get_keymap = _gdk_quartz_display_get_keymap;
-  display_class->get_n_monitors = gdk_quartz_display_get_n_monitors;
-  display_class->get_monitor = gdk_quartz_display_get_monitor;
-  display_class->get_setting = gdk_quartz_display_get_setting;
-
-  ProcessSerialNumber psn = { 0, kCurrentProcess };
-
-  /* Make the current process a foreground application, i.e. an app
-   * with a user interface, in case we're not running from a .app bundle
-   */
-  TransformProcessType (&psn, kProcessTransformToForegroundApplication);
-}
diff --git a/gdk/quartz/gdkdisplay-quartz.h b/gdk/quartz/gdkdisplay-quartz.h
deleted file mode 100644 (file)
index 7d69237..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * gdkdisplay-quartz.h
- *
- * Copyright 2017 Tom Schoonjans 
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_DISPLAY__
-#define __GDK_QUARTZ_DISPLAY__
-
-#include "gdkdisplayprivate.h"
-#include "gdkkeys.h"
-#include "gdksurface.h"
-#include "gdkinternals.h"
-
-G_BEGIN_DECLS
-
-
-struct _GdkQuartzDisplay
-{
-  GdkDisplay parent_instance;
-  GPtrArray *monitors;
-};
-
-struct _GdkQuartzDisplayClass
-{
-  GdkDisplayClass parent_class;
-};
-
-/* Display methods - events */
-void     _gdk_quartz_display_queue_events (GdkDisplay *display);
-gboolean _gdk_quartz_display_has_pending  (GdkDisplay *display);
-
-void       _gdk_quartz_display_event_data_copy (GdkDisplay     *display,
-                                                const GdkEvent *src,
-                                                GdkEvent       *dst);
-void       _gdk_quartz_display_event_data_free (GdkDisplay     *display,
-                                                GdkEvent       *event);
-
-/* Display methods - cursor */
-gboolean   _gdk_quartz_display_supports_cursor_alpha   (GdkDisplay    *display);
-gboolean   _gdk_quartz_display_supports_cursor_color   (GdkDisplay    *display);
-void       _gdk_quartz_display_get_default_cursor_size (GdkDisplay *display,
-                                                        guint      *width,
-                                                        guint      *height);
-void       _gdk_quartz_display_get_maximal_cursor_size (GdkDisplay *display,
-                                                        guint      *width,
-                                                        guint      *height);
-
-/* Display methods - window */
-void       _gdk_quartz_display_before_process_all_updates (GdkDisplay *display);
-void       _gdk_quartz_display_after_process_all_updates  (GdkDisplay *display);
-void       _gdk_quartz_display_create_surface_impl (GdkDisplay    *display,
-                                                   GdkSurface     *window,
-                                                   GdkSurface     *real_parent,
-                                                   GdkSurfaceAttr *attributes);
-
-/* Display methods - keymap */
-GdkKeymap * _gdk_quartz_display_get_keymap (GdkDisplay *display);
-
-
-G_END_DECLS
-
-#endif  /* __GDK_QUARTZ_DISPLAY__ */
-
diff --git a/gdk/quartz/gdkdisplaymanager-quartz.c b/gdk/quartz/gdkdisplaymanager-quartz.c
deleted file mode 100644 (file)
index 2058fcf..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/* GDK - The GIMP Drawing Kit
- * gdkdisplaymanager-quartz.c
- *
- * Copyright (C) 2005 Imendio AB
- * Copyright 2010 Red Hat, Inc.
- *
- * Author: Matthias clasen
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include <ApplicationServices/ApplicationServices.h>
-
-#include "gdkquartzdisplay.h"
-#include "gdkquartzdisplaymanager.h"
-#include "gdkprivate-quartz.h"
-
-#include "gdkdisplaymanagerprivate.h"
-#include "gdkinternals.h"
-
-struct _GdkQuartzDisplayManager
-{
-  GdkDisplayManager parent;
-};
-
-
-G_DEFINE_TYPE (GdkQuartzDisplayManager, gdk_quartz_display_manager, GDK_TYPE_DISPLAY_MANAGER)
-
-static void
-gdk_quartz_display_manager_init (GdkQuartzDisplayManager *manager)
-{
-}
-
-static void
-gdk_quartz_display_manager_finalize (GObject *object)
-{
-  g_error ("A GdkQuartzDisplayManager object was finalized. This should not happen");
-  G_OBJECT_CLASS (gdk_quartz_display_manager_parent_class)->finalize (object);
-}
-
-static void
-gdk_quartz_display_manager_class_init (GdkQuartzDisplayManagerClass *class)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (class);
-  GdkDisplayManagerClass *manager_class = GDK_DISPLAY_MANAGER_CLASS (class);
-
-  object_class->finalize = gdk_quartz_display_manager_finalize;
-}
diff --git a/gdk/quartz/gdkdnd-quartz.c b/gdk/quartz/gdkdnd-quartz.c
deleted file mode 100644 (file)
index 20430a4..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/* gdkdnd-quartz.c
- *
- * Copyright (C) 2005 Imendio AB
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include "gdkdnd.h"
-#include "gdkquartzdnd.h"
-#include "gdkprivate-quartz.h"
-
-
-G_DEFINE_TYPE (GdkQuartzDragContext, gdk_quartz_drag_context, GDK_TYPE_DRAG_CONTEXT)
-
-
-GdkDragContext *_gdk_quartz_drag_source_context = NULL;
-
-GdkDragContext *
-gdk_quartz_drag_source_context_libgtk_only ()
-{
-  return _gdk_quartz_drag_source_context;
-}
-
-GdkDragContext *
-_gdk_quartz_surface_drag_begin (GdkSurface *window,
-                               GdkDevice *device,
-                               GList     *targets,
-                               gint       dx,
-                               gint       dy)
-{
-  g_assert (_gdk_quartz_drag_source_context == NULL);
-
-  /* Create fake context */
-  _gdk_quartz_drag_source_context = g_object_new (GDK_TYPE_QUARTZ_DRAG_CONTEXT,
-                                                  "device", device,
-                                                  NULL);
-
-  _gdk_quartz_drag_source_context->source_surface = window;
-  g_object_ref (window);
-
-  _gdk_quartz_drag_source_context->targets = targets;
-
-  return _gdk_quartz_drag_source_context;
-}
-
-static void
-gdk_quartz_drag_context_drag_drop (GdkDragContext *context,
-                                   guint32         time)
-{
-  /* FIXME: Implement */
-}
-
-static void
-gdk_quartz_drag_context_drag_abort (GdkDragContext *context,
-                                    guint32         time)
-{
-  /* FIXME: Implement */
-}
-
-id
-gdk_quartz_drag_context_get_dragging_info_libgtk_only (GdkDragContext *context)
-{
-  return GDK_QUARTZ_DRAG_CONTEXT (context)->dragging_info;
-}
-
-static void
-gdk_quartz_drag_context_init (GdkQuartzDragContext *context)
-{
-}
-
-static void
-gdk_quartz_drag_context_finalize (GObject *object)
-{
-  G_OBJECT_CLASS (gdk_quartz_drag_context_parent_class)->finalize (object);
-}
-
-static void
-gdk_quartz_drag_context_class_init (GdkQuartzDragContextClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GdkDragContextClass *context_class = GDK_DRAG_CONTEXT_CLASS (klass);
-
-  object_class->finalize = gdk_quartz_drag_context_finalize;
-
-  context_class->drag_abort = gdk_quartz_drag_context_drag_abort;
-  context_class->drag_drop = gdk_quartz_drag_context_drag_drop;
-}
diff --git a/gdk/quartz/gdkdnd-quartz.h b/gdk/quartz/gdkdnd-quartz.h
deleted file mode 100644 (file)
index 990904e..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/* gdkdnd-quartz.h
- *
- * Copyright (C) 2005 Imendio AB
- * Copyright (C) 2010  Kristian Rietveld  <kris@gtk.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_DND__
-#define __GDK_QUARTZ_DND__
-
-#include <gdkdndprivate.h>
-#include "gdkquartzdnd.h"
-
-#include <AppKit/AppKit.h>
-
-G_BEGIN_DECLS
-
-struct _GdkQuartzDragContext
-{
-  GdkDragContext context;
-
-  id <NSDraggingInfo> dragging_info;
-  GdkDevice *device;
-};
-
-struct _GdkQuartzDragContextClass
-{
-  GdkDragContextClass context_class;
-};
-
-G_END_DECLS
-
-#endif /* __GDK_QUARTZ_DND__ */
diff --git a/gdk/quartz/gdkeventloop-quartz.c b/gdk/quartz/gdkeventloop-quartz.c
deleted file mode 100644 (file)
index 031a207..0000000
+++ /dev/null
@@ -1,1046 +0,0 @@
-#include "config.h"
-
-#include <glib.h>
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <unistd.h>
-
-#include "gdkprivate-quartz.h"
-#include <gdk/gdkdisplayprivate.h>
-
-/* 
- * This file implementations integration between the GLib main loop and
- * the native system of the Core Foundation run loop and Cocoa event
- * handling. There are basically two different cases that we need to
- * handle: either the GLib main loop is in control (the application
- * has called gtk_main(), or is otherwise iterating the main loop), or
- * CFRunLoop is in control (we are in a modal operation such as window
- * resizing or drag-and-drop.)
- *
- * When the GLib main loop is in control we integrate in native event
- * handling in two ways: first we add a GSource that handles checking
- * whether there are native events available, translating native events
- * to GDK events, and dispatching GDK events. Second we replace the
- * "poll function" of the GLib main loop with our own version that knows
- * how to wait for both the file descriptors and timeouts that GLib is
- * interested in and also for incoming native events.
- *
- * When CFRunLoop is in control, we integrate in GLib main loop handling
- * by adding a "run loop observer" that gives us notification at various
- * points in the run loop cycle. We map these points onto the corresponding
- * stages of the GLib main loop (prepare, check, dispatch), and make the
- * appropriate calls into GLib.
- *
- * Both cases share a single problem: the OS X API’s don’t allow us to
- * wait simultaneously for file descriptors and for events. So when we
- * need to do a blocking wait that includes file descriptor activity, we
- * push the actual work of calling select() to a helper thread (the
- * "select thread") and wait for native events in the main thread.
- *
- * The main known limitation of this code is that if a callback is triggered
- * via the OS X run loop while we are "polling" (in either case described
- * above), iteration of the GLib main loop is not possible from within
- * that callback. If the programmer tries to do so explicitly, then they
- * will get a warning from GLib "main loop already active in another thread".
- */
-
-/******* State for run loop iteration *******/
-
-/* Count of number of times we've gotten an "Entry" notification for
- * our run loop observer.
- */
-static int current_loop_level = 0;
-
-/* Run loop level at which we acquired ownership of the GLib main
- * loop. See note in run_loop_entry(). -1 means that we don’t have
- * ownership
- */ 
-static int acquired_loop_level = -1;
-
-/* Between run_loop_before_waiting() and run_loop_after_waiting();
- * whether we need to call select_thread_collect_poll()
- */
-static gboolean run_loop_polling_async = FALSE;
-
-/* Between run_loop_before_waiting() and run_loop_after_waiting();
- * max_priority to pass to g_main_loop_check()
- */
-static gint run_loop_max_priority;
-
-/* Timer that we've added to wake up the run loop when a GLib timeout
- */
-static CFRunLoopTimerRef run_loop_timer = NULL;
-
-/* These are the file descriptors that are we are polling out of
- * the run loop. (We keep the array around and reuse it to avoid
- * constant allocations.)
- */
-#define RUN_LOOP_POLLFDS_INITIAL_SIZE 16
-static GPollFD *run_loop_pollfds;
-static guint run_loop_pollfds_size; /* Allocated size of the array */
-static guint run_loop_n_pollfds;    /* Number of file descriptors in the array */
-
-/******* Other global variables *******/
-
-/* Since we count on replacing the GLib main loop poll function as our
- * method of integrating Cocoa event handling into the GLib main loop
- * we need to make sure that the poll function is always called even
- * when there are no file descriptors that need to be polled. To do
- * this, we add a dummy GPollFD to our event source with a file
- * descriptor of “-1”. Then any time that GLib is polling the event
- * source, it will call our poll function.
- */
-static GPollFD event_poll_fd;
-
-/* Current NSEvents that we've gotten from Cocoa but haven't yet converted
- * to GdkEvents. We wait until our dispatch() function to do the conversion
- * since the conversion can conceivably cause signals to be emitted
- * or other things that shouldn’t happen inside a poll function.
- */
-static GQueue *current_events;
-
-/* The default poll function for GLib; we replace this with our own
- * Cocoa-aware version and then call the old version to do actual
- * file descriptor polling. There’s no actual need to chain to the
- * old one; we could reimplement the same functionality from scratch,
- * but since the default implementation does the right thing, why
- * bother.
- */
-static GPollFunc old_poll_func;
-
-/* Reference to the run loop of the main thread. (There is a unique
- * CFRunLoop per thread.)
- */
-static CFRunLoopRef main_thread_run_loop;
-
-/* Normally the Cocoa main loop maintains an NSAutoReleasePool and frees
- * it on every iteration. Since we are replacing the main loop we have
- * to provide this functionality ourself. We free and replace the
- * auto-release pool in our sources prepare() function.
- */
-static NSAutoreleasePool *autorelease_pool;
-
-/* Flag when we've called nextEventMatchingMask ourself; this triggers
- * a run loop iteration, so we need to detect that and avoid triggering
- * our "run the GLib main looop while the run loop is active machinery.
- */
-static gint getting_events = 0;
-
-/************************************************************
- *********              Select Thread               *********
- ************************************************************/
-
-/* The states in our state machine, see comments in select_thread_func()
- * for descriptions of each state
- */
-typedef enum {
-  BEFORE_START,
-  WAITING,
-  POLLING_QUEUED,
-  POLLING_RESTART,
-  POLLING_DESCRIPTORS,
-} SelectThreadState;
-
-#ifdef G_ENABLE_DEBUG
-static const char *const state_names[]  = {
-  "BEFORE_START",
-  "WAITING",
-  "POLLING_QUEUED",
-  "POLLING_RESTART",
-  "POLLING_DESCRIPTORS"
-};
-#endif
-
-static SelectThreadState select_thread_state = BEFORE_START;
-
-static pthread_t select_thread;
-static pthread_mutex_t select_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t select_thread_cond = PTHREAD_COND_INITIALIZER;
-
-#define SELECT_THREAD_LOCK() pthread_mutex_lock (&select_thread_mutex)
-#define SELECT_THREAD_UNLOCK() pthread_mutex_unlock (&select_thread_mutex)
-#define SELECT_THREAD_SIGNAL() pthread_cond_signal (&select_thread_cond)
-#define SELECT_THREAD_WAIT() pthread_cond_wait (&select_thread_cond, &select_thread_mutex)
-
-/* These are the file descriptors that the select thread is currently
- * polling.
- */
-static GPollFD *current_pollfds;
-static guint current_n_pollfds;
-
-/* These are the file descriptors that the select thread should pick
- * up and start polling when it has a chance.
- */
-static GPollFD *next_pollfds;
-static guint next_n_pollfds;
-
-/* Pipe used to wake up the select thread */
-static gint select_thread_wakeup_pipe[2];
-
-/* Run loop source used to wake up the main thread */
-static CFRunLoopSourceRef select_main_thread_source;
-
-static void
-select_thread_set_state (SelectThreadState new_state)
-{
-  gboolean old_state;
-
-  if (select_thread_state == new_state)
-    return;
-
-  GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Select thread state: %s => %s", state_names[select_thread_state], state_names[new_state]));
-
-  old_state = select_thread_state;
-  select_thread_state = new_state;
-  if (old_state == WAITING && new_state != WAITING)
-    SELECT_THREAD_SIGNAL ();
-}
-
-static void
-signal_main_thread (void)
-{
-  GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Waking up main thread"));
-
-  /* If we are in nextEventMatchingMask, then we need to make sure an
-   * event gets queued, otherwise it's enough to simply wake up the
-   * main thread run loop
-   */
-  if (!run_loop_polling_async)
-    CFRunLoopSourceSignal (select_main_thread_source);
-
-  /* Don't check for CFRunLoopIsWaiting() here because it causes a
-   * race condition (the loop could go into waiting state right after
-   * we checked).
-   */
-  CFRunLoopWakeUp (main_thread_run_loop);
-}
-
-static void *
-select_thread_func (void *arg)
-{
-  char c;
-  
-  SELECT_THREAD_LOCK ();
-
-  while (TRUE)
-    {
-      switch (select_thread_state)
-       {
-       case BEFORE_START:
-         /* The select thread has not been started yet
-          */
-         g_assert_not_reached ();
-         
-       case WAITING:
-         /* Waiting for a set of file descriptors to be submitted by the main thread
-          *
-          *  => POLLING_QUEUED: main thread submits a set of file descriptors
-          */ 
-         SELECT_THREAD_WAIT ();
-         break;
-         
-       case POLLING_QUEUED:
-         /* Waiting for a set of file descriptors to be submitted by the main thread
-          *
-          *  => POLLING_DESCRIPTORS: select thread picks up the file descriptors to begin polling
-          */ 
-         g_free (current_pollfds);
-         
-         current_pollfds = next_pollfds;
-         current_n_pollfds = next_n_pollfds;
-
-         next_pollfds = NULL;
-         next_n_pollfds = 0;
-
-         select_thread_set_state (POLLING_DESCRIPTORS);
-         break;
-         
-       case POLLING_RESTART:
-         /* Select thread is currently polling a set of file descriptors, main thread has
-          * began a new iteration with the same set of file descriptors. We don't want to
-          * wake the select thread up and wait for it to restart immediately, but to avoid
-          * a race (described below in select_thread_start_polling()) we need to recheck after
-          * polling completes.
-          *
-          * => POLLING_DESCRIPTORS: select completes, main thread rechecks by polling again
-          * => POLLING_QUEUED: main thread submits a new set of file descriptors to be polled
-          */
-         select_thread_set_state (POLLING_DESCRIPTORS);
-         break;
-
-       case POLLING_DESCRIPTORS:
-         /* In the process of polling the file descriptors
-          *
-          *  => WAITING: polling completes when a file descriptor becomes active
-          *  => POLLING_QUEUED: main thread submits a new set of file descriptors to be polled
-          *  => POLLING_RESTART: main thread begins a new iteration with the same set file descriptors
-          */ 
-         SELECT_THREAD_UNLOCK ();
-         old_poll_func (current_pollfds, current_n_pollfds, -1);
-         SELECT_THREAD_LOCK ();
-
-         read (select_thread_wakeup_pipe[0], &c, 1);
-
-         if (select_thread_state == POLLING_DESCRIPTORS)
-           {
-             signal_main_thread ();
-             select_thread_set_state (WAITING);
-           }
-         break;
-       }
-    }
-}
-
-static void 
-got_fd_activity (void *info)
-{
-  NSEvent *event;
-
-  /* Post a message so we'll break out of the message loop */
-  event = [NSEvent otherEventWithType: NSApplicationDefined
-                            location: NSZeroPoint
-                       modifierFlags: 0
-                           timestamp: 0
-                        windowNumber: 0
-                             context: nil
-                              subtype: GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP
-                               data1: 0 
-                               data2: 0];
-
-  [NSApp postEvent:event atStart:YES];
-}
-
-static void
-select_thread_start (void)
-{
-  g_return_if_fail (select_thread_state == BEFORE_START);
-  
-  pipe (select_thread_wakeup_pipe);
-  fcntl (select_thread_wakeup_pipe[0], F_SETFL, O_NONBLOCK);
-
-  CFRunLoopSourceContext source_context = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, got_fd_activity };
-  select_main_thread_source = CFRunLoopSourceCreate (NULL, 0, &source_context);
-  
-  CFRunLoopAddSource (main_thread_run_loop, select_main_thread_source, kCFRunLoopCommonModes);
-
-  select_thread_state = WAITING;
-  
-  while (TRUE)
-    {
-      if (pthread_create (&select_thread, NULL, select_thread_func, NULL) == 0)
-         break;
-
-      g_warning ("Failed to create select thread, sleeping and trying again");
-      sleep (1);
-    }
-}
-
-#ifdef G_ENABLE_DEBUG
-static void
-dump_poll_result (GPollFD *ufds,
-                 guint    nfds)
-{
-  GString *s;
-  gint i;
-
-  s = g_string_new ("");
-  for (i = 0; i < nfds; i++)
-    {
-      if (ufds[i].fd >= 0 && ufds[i].revents)
-       {
-          g_string_append_printf (s, " %d:", ufds[i].fd);
-         if (ufds[i].revents & G_IO_IN)
-            g_string_append (s, " in");
-         if (ufds[i].revents & G_IO_OUT)
-           g_string_append (s, " out");
-         if (ufds[i].revents & G_IO_PRI)
-           g_string_append (s, " pri");
-         g_string_append (s, "\n");
-       }
-    }
-  g_message ("%s", s->str);
-  g_string_free (s, TRUE);
-}
-#endif
-
-gboolean
-pollfds_equal (GPollFD *old_pollfds,
-              guint    old_n_pollfds,
-              GPollFD *new_pollfds,
-              guint    new_n_pollfds)
-{
-  gint i;
-  
-  if (old_n_pollfds != new_n_pollfds)
-    return FALSE;
-
-  for (i = 0; i < old_n_pollfds; i++)
-    {
-      if (old_pollfds[i].fd != new_pollfds[i].fd ||
-         old_pollfds[i].events != new_pollfds[i].events)
-       return FALSE;
-    }
-
-  return TRUE;
-}
-
-/* Begins a polling operation with the specified GPollFD array; the 
- * timeout is used only to tell if the polling operation is blocking
- * or non-blocking.
- *
- * Returns:
- *  -1: No file descriptors ready, began asynchronous poll
- *   0: No file descriptors ready, asynchronous poll not needed
- * > 0: Number of file descriptors ready
- */
-static gint
-select_thread_start_poll (GPollFD *ufds,
-                         guint    nfds,                          gint     timeout)
-{
-  gint n_ready;
-  gboolean have_new_pollfds = FALSE;
-  gint poll_fd_index = -1;
-  gint i;
-
-  for (i = 0; i < nfds; i++)
-    if (ufds[i].fd == -1)
-      {
-       poll_fd_index = i;
-       break;
-      }
-  
-  if (nfds == 0 ||
-      (nfds == 1 && poll_fd_index >= 0))
-    {
-      GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Nothing to poll"));
-      return 0;
-    }
-
-  /* If we went immediately to an async poll, then we might decide to
-   * dispatch idle functions when higher priority file descriptor sources
-   * are ready to be dispatched. So we always need to first check
-   * check synchronously with a timeout of zero, and only when no
-   * sources are immediately ready, go to the asynchronous poll.
-   *
-   * Of course, if the timeout passed in is 0, then the synchronous
-   * check is sufficient and we never need to do the asynchronous poll.
-   */
-  n_ready = old_poll_func (ufds, nfds, 0);
-  if (n_ready > 0 || timeout == 0)
-    {
-#ifdef G_ENABLE_DEBUG
-      if ((_gdk_debug_flags & GDK_DEBUG_EVENTLOOP) && n_ready > 0)
-       {
-         g_message ("EventLoop: Found ready file descriptors before waiting");
-         dump_poll_result (ufds, nfds);
-       }
-#endif
-  
-      return n_ready;
-    }
-  
-  SELECT_THREAD_LOCK ();
-
-  if (select_thread_state == BEFORE_START)
-    {
-      select_thread_start ();
-    }
-  
-  if (select_thread_state == POLLING_QUEUED)
-    {
-      /* If the select thread hasn't picked up the set of file descriptors yet
-       * then we can simply replace an old stale set with a new set.
-       */
-      if (!pollfds_equal (ufds, nfds, next_pollfds, next_n_pollfds - 1))
-       {
-         g_free (next_pollfds);
-         next_pollfds = NULL;
-         next_n_pollfds = 0;
-         
-         have_new_pollfds = TRUE;
-       }
-    }
-  else if (select_thread_state == POLLING_RESTART || select_thread_state == POLLING_DESCRIPTORS)
-    {
-      /* If we are already in the process of polling the right set of file descriptors,
-       * there's no need for us to immediately force the select thread to stop polling
-       * and then restart again. And avoiding doing so increases the efficiency considerably
-       * in the common case where we have a set of basically inactive file descriptors that
-       * stay unchanged present as we process many events.
-       *
-       * However, we have to be careful that we don't hit the following race condition
-       *  Select Thread              Main Thread
-       *  -----------------          ---------------
-       *  Polling Completes
-       *                             Reads data or otherwise changes file descriptor state
-       *                             Checks if polling is current
-       *                             Does nothing (*)
-       *                             Releases lock
-       *  Acquires lock
-       *  Marks polling as complete
-       *  Wakes main thread
-       *                             Receives old stale file descriptor state
-       * 
-       * To avoid this, when the new set of poll descriptors is the same as the current
-       * one, we transition to the POLLING_RESTART stage at the point marked (*). When
-       * the select thread wakes up from the poll because a file descriptor is active, if
-       * the state is POLLING_RESTART it immediately begins polling same the file descriptor
-       * set again. This normally will just return the same set of active file descriptors
-       * as the first time, but in sequence described above will properly update the
-       * file descriptor state.
-       *
-       * Special case: this RESTART logic is not needed if the only FD is the internal GLib
-       * "wakeup pipe" that is presented when threads are initialized.
-       *
-       * P.S.: The harm in the above sequence is mostly that sources can be signalled
-       *   as ready when they are no longer ready. This may prompt a blocking read
-       *   from a file descriptor that hangs.
-       */
-      if (!pollfds_equal (ufds, nfds, current_pollfds, current_n_pollfds - 1))
-       have_new_pollfds = TRUE;
-      else
-       {
-         if (!((nfds == 1 && poll_fd_index < 0 && g_thread_supported ()) ||
-               (nfds == 2 && poll_fd_index >= 0 && g_thread_supported ())))
-           select_thread_set_state (POLLING_RESTART);
-       }
-    }
-  else
-    have_new_pollfds = TRUE;
-
-  if (have_new_pollfds)
-    {
-      GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Submitting a new set of file descriptor to the select thread"));
-      
-      g_assert (next_pollfds == NULL);
-      
-      next_n_pollfds = nfds + 1;
-      next_pollfds = g_new (GPollFD, nfds + 1);
-      memcpy (next_pollfds, ufds, nfds * sizeof (GPollFD));
-  
-      next_pollfds[nfds].fd = select_thread_wakeup_pipe[0];
-      next_pollfds[nfds].events = G_IO_IN;
-  
-      if (select_thread_state != POLLING_QUEUED && select_thread_state != WAITING)
-       {
-         if (select_thread_wakeup_pipe[1])
-           {
-             char c = 'A';
-             write (select_thread_wakeup_pipe[1], &c, 1);
-           }
-       }
-      
-      select_thread_set_state (POLLING_QUEUED);
-    }
-  
-  SELECT_THREAD_UNLOCK ();
-
-  return -1;
-}
-
-/* End an asynchronous polling operation started with
- * select_thread_collect_poll(). This must be called if and only if
- * select_thread_start_poll() return -1. The GPollFD array passed
- * in must be identical to the one passed to select_thread_start_poll().
- *
- * The results of the poll are written into the GPollFD array passed in.
- *
- * Returns: number of file descriptors ready
- */
-static int
-select_thread_collect_poll (GPollFD *ufds, guint nfds)
-{
-  gint i;
-  gint n_ready = 0;
-  
-  SELECT_THREAD_LOCK ();
-
-  if (select_thread_state == WAITING) /* The poll completed */
-    {
-      for (i = 0; i < nfds; i++)
-       {
-         if (ufds[i].fd == -1)
-           continue;
-         
-         g_assert (ufds[i].fd == current_pollfds[i].fd);
-         g_assert (ufds[i].events == current_pollfds[i].events);
-
-         if (current_pollfds[i].revents)
-           {
-             ufds[i].revents = current_pollfds[i].revents;
-             n_ready++;
-           }
-       }
-      
-#ifdef G_ENABLE_DEBUG
-      if (_gdk_debug_flags & GDK_DEBUG_EVENTLOOP)
-       {
-         g_message ("EventLoop: Found ready file descriptors after waiting");
-         dump_poll_result (ufds, nfds);
-       }
-#endif
-    }
-
-  SELECT_THREAD_UNLOCK ();
-
-  return n_ready;
-}
-
-/************************************************************
- *********             Main Loop Source             *********
- ************************************************************/
-
-gboolean
-_gdk_quartz_event_loop_check_pending (void)
-{
-  return current_events && current_events->head;
-}
-
-NSEvent*
-_gdk_quartz_event_loop_get_pending (void)
-{
-  NSEvent *event = NULL;
-
-  if (current_events)
-    event = g_queue_pop_tail (current_events);
-
-  return event;
-}
-
-void
-_gdk_quartz_event_loop_release_event (NSEvent *event)
-{
-  [event release];
-}
-
-static gboolean
-gdk_event_prepare (GSource *source,
-                  gint    *timeout)
-{
-  gboolean retval;
-
-  /* The prepare stage is the stage before the main loop starts polling
-   * and dispatching events. The autorelease poll is drained here for
-   * the preceding main loop iteration or, in case of the first iteration,
-   * for the operations carried out between event loop initialization and
-   * this first iteration.
-   *
-   * The autorelease poll must only be drained when the following conditions
-   * apply:
-   *  - We are at the base CFRunLoop level (indicated by current_loop_level),
-   *  - We are at the base g_main_loop level (indicated by
-   *    g_main_depth())
-   *  - We are at the base poll_func level (indicated by getting events).
-   *
-   * Messing with the autorelease pool at any level of nesting can cause access
-   * to deallocated memory because autorelease_pool is static and releasing a
-   * pool will cause all pools allocated inside of it to be released as well.
-   */
-  if (current_loop_level == 0 && g_main_depth() == 0 && getting_events == 0)
-    {
-      if (autorelease_pool)
-        [autorelease_pool drain];
-
-      autorelease_pool = [[NSAutoreleasePool alloc] init];
-    }
-
-  *timeout = -1;
-
-  if (_gdk_display->event_pause_count > 0)
-    retval = _gdk_event_queue_find_first (_gdk_display) != NULL;
-  else
-    retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
-              _gdk_quartz_event_loop_check_pending ());
-
-  return retval;
-}
-
-static gboolean
-gdk_event_check (GSource *source)
-{
-  gboolean retval;
-
-  if (_gdk_display->event_pause_count > 0)
-    retval = _gdk_event_queue_find_first (_gdk_display) != NULL;
-  else
-    retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
-              _gdk_quartz_event_loop_check_pending ());
-
-  return retval;
-}
-
-static gboolean
-gdk_event_dispatch (GSource     *source,
-                   GSourceFunc  callback,
-                   gpointer     user_data)
-{
-  GdkEvent *event;
-
-  _gdk_quartz_display_queue_events (_gdk_display);
-
-  event = _gdk_event_unqueue (_gdk_display);
-
-  if (event)
-    {
-      _gdk_event_emit (event);
-
-      g_object_unref (event);
-    }
-
-  return TRUE;
-}
-
-static GSourceFuncs event_funcs = {
-  gdk_event_prepare,
-  gdk_event_check,
-  gdk_event_dispatch,
-  NULL
-};
-
-/************************************************************
- *********             Our Poll Function            *********
- ************************************************************/
-
-static gint
-poll_func (GPollFD *ufds,
-          guint    nfds,
-          gint     timeout_)
-{
-  NSEvent *event;
-  NSDate *limit_date;
-  gint n_ready;
-
-  static GPollFD *last_ufds;
-
-  last_ufds = ufds;
-
-  n_ready = select_thread_start_poll (ufds, nfds, timeout_);
-  if (n_ready > 0)
-    timeout_ = 0;
-
-  if (timeout_ == -1)
-    limit_date = [NSDate distantFuture];
-  else if (timeout_ == 0)
-    limit_date = [NSDate distantPast];
-  else
-    limit_date = [NSDate dateWithTimeIntervalSinceNow:timeout_/1000.0];
-
-  getting_events++;
-  event = [NSApp nextEventMatchingMask: NSAnyEventMask
-                            untilDate: limit_date
-                               inMode: NSDefaultRunLoopMode
-                               dequeue: YES];
-  getting_events--;
-
-  /* We check if last_ufds did not change since the time this function was
-   * called. It is possible that a recursive main loop (and thus recursive
-   * invocation of this poll function) is triggered while in
-   * nextEventMatchingMask:. If during that time new fds are added,
-   * the cached fds array might be replaced in g_main_context_iterate().
-   * So, we should avoid accessing the old fd array (still pointed at by
-   * ufds) here in that case, since it might have been freed. We avoid this
-   * by not calling the collect stage.
-   */
-  if (last_ufds == ufds && n_ready < 0)
-    n_ready = select_thread_collect_poll (ufds, nfds);
-      
-  if (event &&
-      [event type] == NSApplicationDefined &&
-      [event subtype] == GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP)
-    {
-      /* Just used to wake us up; if an event and a FD arrived at the same
-       * time; could have come from a previous iteration in some cases,
-       * but the spurious wake up is harmless if a little inefficient.
-       */
-      event = NULL;
-    }
-
-  if (event) 
-    {
-      if (!current_events)
-        current_events = g_queue_new ();
-      g_queue_push_head (current_events, [event retain]);
-    }
-
-  return n_ready;
-}
-
-/************************************************************
- *********  Running the main loop out of CFRunLoop  *********
- ************************************************************/
-
-/* Wrapper around g_main_context_query() that handles reallocating
- * run_loop_pollfds up to the proper size
- */
-static gint
-query_main_context (GMainContext *context,
-                   int           max_priority,
-                   int          *timeout)
-{
-  gint nfds;
-  
-  if (!run_loop_pollfds)
-    {
-      run_loop_pollfds_size = RUN_LOOP_POLLFDS_INITIAL_SIZE;
-      run_loop_pollfds = g_new (GPollFD, run_loop_pollfds_size);
-    }
-
-  while ((nfds = g_main_context_query (context, max_priority, timeout,
-                                      run_loop_pollfds, 
-                                      run_loop_pollfds_size)) > run_loop_pollfds_size)
-    {
-      g_free (run_loop_pollfds);
-      run_loop_pollfds_size = nfds;
-      run_loop_pollfds = g_new (GPollFD, nfds);
-    }
-
-  return nfds;
-}
-
-static void
-run_loop_entry (void)
-{
-  if (acquired_loop_level == -1)
-    {
-      if (g_main_context_acquire (NULL))
-       {
-         GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Beginning tracking run loop activity"));
-         acquired_loop_level = current_loop_level;
-       }
-      else
-       {
-         /* If we fail to acquire the main context, that means someone is iterating
-          * the main context in a different thread; we simply wait until this loop
-          * exits and then try again at next entry. In general, iterating the loop
-          * from a different thread is rare: it is only possible when GDK threading
-          * is initialized and is not frequently used even then. So, we hope that
-          * having GLib main loop iteration blocked in the combination of that and
-          * a native modal operation is a minimal problem. We could imagine using a
-          * thread that does g_main_context_wait() and then wakes us back up, but
-          * the gain doesn't seem worth the complexity.
-          */
-         GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Can't acquire main loop; skipping tracking run loop activity"));
-       }
-    }
-}
-
-static void
-run_loop_before_timers (void)
-{
-}
-
-static void
-run_loop_before_sources (void)
-{
-  GMainContext *context = g_main_context_default ();
-  gint max_priority;
-  gint nfds;
-
-  /* Before we let the CFRunLoop process sources, we want to check if there
-   * are any pending GLib main loop sources more urgent than
-   * G_PRIORITY_DEFAULT that need to be dispatched. (We consider all activity
-   * from the CFRunLoop to have a priority of G_PRIORITY_DEFAULT.) If no
-   * sources are processed by the CFRunLoop, then processing will continue
-   * on to the BeforeWaiting stage where we check for lower priority sources.
-   */
-  
-  g_main_context_prepare (context, &max_priority); 
-  max_priority = MIN (max_priority, G_PRIORITY_DEFAULT);
-
-  /* We ignore the timeout that query_main_context () returns since we'll
-   * always query again before waiting.
-   */
-  nfds = query_main_context (context, max_priority, NULL);
-
-  if (nfds)
-    old_poll_func (run_loop_pollfds, nfds, 0);
-  
-  if (g_main_context_check (context, max_priority, run_loop_pollfds, nfds))
-    {
-      GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Dispatching high priority sources"));
-      g_main_context_dispatch (context);
-    }
-}
-
-static void
-dummy_timer_callback (CFRunLoopTimerRef  timer,
-                     void              *info)
-{
-  /* Nothing; won't normally even be called */
-}
-
-static void
-run_loop_before_waiting (void)
-{
-  GMainContext *context = g_main_context_default ();
-  gint timeout;
-  gint n_ready;
-
-  /* At this point, the CFRunLoop is ready to wait. We start a GMain loop
-   * iteration by calling the check() and query() stages. We start a
-   * poll, and if it doesn't complete immediately we let the run loop
-   * go ahead and sleep. Before doing that, if there was a timeout from
-   * GLib, we set up a CFRunLoopTimer to wake us up.
-   */
-  
-  g_main_context_prepare (context, &run_loop_max_priority); 
-  
-  run_loop_n_pollfds = query_main_context (context, run_loop_max_priority, &timeout);
-
-  n_ready = select_thread_start_poll (run_loop_pollfds, run_loop_n_pollfds, timeout);
-
-  if (n_ready > 0 || timeout == 0)
-    {
-      /* We have stuff to do, no sleeping allowed! */
-      CFRunLoopWakeUp (main_thread_run_loop);
-    }
-  else if (timeout > 0)
-    {
-      /* We need to get the run loop to break out of its wait when our timeout
-       * expires. We do this by adding a dummy timer that we'll remove immediately
-       * after the wait wakes up.
-       */
-      GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Adding timer to wake us up in %d milliseconds", timeout));
-      
-      run_loop_timer = CFRunLoopTimerCreate (NULL, /* allocator */
-                                            CFAbsoluteTimeGetCurrent () + timeout / 1000.,
-                                            0, /* interval (0=does not repeat) */
-                                            0, /* flags */
-                                            0, /* order (priority) */
-                                            dummy_timer_callback,
-                                            NULL);
-
-      CFRunLoopAddTimer (main_thread_run_loop, run_loop_timer, kCFRunLoopCommonModes);
-    }
-  
-  run_loop_polling_async = n_ready < 0;
-}
-
-static void
-run_loop_after_waiting (void)
-{
-  GMainContext *context = g_main_context_default ();
-
-  /* After sleeping, we finish of the GMain loop iteratin started in before_waiting()
-   * by doing the check() and dispatch() stages.
-   */
-
-  if (run_loop_timer)
-    {
-      CFRunLoopRemoveTimer (main_thread_run_loop, run_loop_timer, kCFRunLoopCommonModes);
-      CFRelease (run_loop_timer);
-      run_loop_timer = NULL;
-    }
-  
-  if (run_loop_polling_async)
-    {
-      select_thread_collect_poll (run_loop_pollfds, run_loop_n_pollfds);
-      run_loop_polling_async = FALSE;
-    }
-  
-  if (g_main_context_check (context, run_loop_max_priority, run_loop_pollfds, run_loop_n_pollfds))
-    {
-      GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Dispatching after waiting"));
-      g_main_context_dispatch (context);
-    }
-}
-
-static void
-run_loop_exit (void)
-{
-  /* + 1 because we decrement current_loop_level separately in observer_callback() */
-  if ((current_loop_level + 1) == acquired_loop_level)
-    {
-      g_main_context_release (NULL);
-      acquired_loop_level = -1;
-      GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Ended tracking run loop activity"));
-    }
-}
-
-static void
-run_loop_observer_callback (CFRunLoopObserverRef observer,
-                           CFRunLoopActivity    activity,
-                           void                *info)
-{
-  switch (activity)
-    {
-    case kCFRunLoopEntry:
-      current_loop_level++;
-      break;
-    case kCFRunLoopExit:
-      g_return_if_fail (current_loop_level > 0);
-      current_loop_level--;
-      break;
-    default:
-      break;
-    }
-
-  if (getting_events > 0) /* Activity we triggered */
-    return;
-
-  switch (activity)
-    {
-    case kCFRunLoopEntry:
-      run_loop_entry ();
-      break;
-    case kCFRunLoopBeforeTimers:
-      run_loop_before_timers ();
-      break;
-    case kCFRunLoopBeforeSources:
-      run_loop_before_sources ();
-      break;
-    case kCFRunLoopBeforeWaiting:
-      run_loop_before_waiting ();
-      break;
-    case kCFRunLoopAfterWaiting:
-      run_loop_after_waiting ();
-      break;
-    case kCFRunLoopExit:
-      run_loop_exit ();
-      break;
-    default:
-      break;
-    }
-}
-
-/************************************************************/
-
-void
-_gdk_quartz_event_loop_init (void)
-{
-  GSource *source;
-  CFRunLoopObserverRef observer;
-
-  /* Hook into the GLib main loop */
-
-  event_poll_fd.events = G_IO_IN;
-  event_poll_fd.fd = -1;
-
-  source = g_source_new (&event_funcs, sizeof (GSource));
-  g_source_set_name (source, "GDK Quartz event source"); 
-  g_source_add_poll (source, &event_poll_fd);
-  g_source_set_priority (source, GDK_PRIORITY_EVENTS);
-  g_source_set_can_recurse (source, TRUE);
-  g_source_attach (source, NULL);
-
-  old_poll_func = g_main_context_get_poll_func (NULL);
-  g_main_context_set_poll_func (NULL, poll_func);
-  
-  /* Hook into the the CFRunLoop for the main thread */
-
-  main_thread_run_loop = CFRunLoopGetCurrent ();
-
-  observer = CFRunLoopObserverCreate (NULL, /* default allocator */
-                                     kCFRunLoopAllActivities,
-                                     true, /* repeats: not one-shot */
-                                     0, /* order (priority) */
-                                     run_loop_observer_callback,
-                                     NULL);
-                                    
-  CFRunLoopAddObserver (main_thread_run_loop, observer, kCFRunLoopCommonModes);
-  
-  /* Initialize our autorelease pool */
-
-  autorelease_pool = [[NSAutoreleasePool alloc] init];
-}
diff --git a/gdk/quartz/gdkevents-quartz.c b/gdk/quartz/gdkevents-quartz.c
deleted file mode 100644 (file)
index 49d5cc6..0000000
+++ /dev/null
@@ -1,1807 +0,0 @@
-/* gdkevents-quartz.c
- *
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- * Copyright (C) 1998-2002 Tor Lillqvist
- * Copyright (C) 2005-2008 Imendio AB
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <sys/types.h>
-#include <sys/sysctl.h>
-#include <pthread.h>
-#include <unistd.h>
-
-#import <Cocoa/Cocoa.h>
-#include <Carbon/Carbon.h>
-
-#include <gdk/gdkdisplayprivate.h>
-
-#include "gdkkeysyms.h"
-#include "gdkquartz.h"
-#include "gdkquartzdisplay.h"
-#include "gdkprivate-quartz.h"
-#include "gdkquartzdevicemanager-core.h"
-
-#define GRIP_WIDTH 15
-#define GRIP_HEIGHT 15
-#define GDK_LION_RESIZE 5
-
-#define SURFACE_IS_TOPLEVEL(window)      TRUE
-
-/* This is the window corresponding to the key window */
-static GdkSurface   *current_keyboard_window;
-
-
-static void append_event                        (GdkEvent  *event,
-                                                 gboolean   windowing);
-
-static GdkSurface *find_toplevel_under_pointer   (GdkDisplay *display,
-                                                 NSPoint     screen_point,
-                                                 gint       *x,
-                                                 gint       *y);
-
-
-static void
-gdk_quartz_ns_notification_callback (CFNotificationCenterRef  center,
-                                     void                    *observer,
-                                     CFStringRef              name,
-                                     const void              *object,
-                                     CFDictionaryRef          userInfo)
-{
-  const char *setting = NULL;
-
-  /* Translate name */
-  if (CFStringCompare (name,
-                       CFSTR("AppleNoRedisplayAppearancePreferenceChanged"),
-                       0) == kCFCompareEqualTo)
-    setting = "gtk-primary-button-warps-slider";
-
-  if (!setting)
-    return;
-
-  gdk_display_setting_changed (_gdk_display, setting);
-}
-
-static void
-gdk_quartz_events_init_notifications (void)
-{
-  static gboolean notifications_initialized = FALSE;
-
-  if (notifications_initialized)
-    return;
-  notifications_initialized = TRUE;
-
-  /* Initialize any handlers for notifications we want to push to GTK
-   * through GdkEventSettings.
-   */
-
-  /* This is an undocumented *distributed* notification to listen for changes
-   * in scrollbar jump behavior. It is used by LibreOffice and WebKit as well.
-   */
-  CFNotificationCenterAddObserver (CFNotificationCenterGetDistributedCenter (),
-                                   NULL,
-                                   &gdk_quartz_ns_notification_callback,
-                                   CFSTR ("AppleNoRedisplayAppearancePreferenceChanged"),
-                                   NULL,
-                                   CFNotificationSuspensionBehaviorDeliverImmediately);
-}
-
-void
-_gdk_quartz_events_init (void)
-{
-  _gdk_quartz_event_loop_init ();
-  gdk_quartz_events_init_notifications ();
-
-  current_keyboard_window = g_object_ref (_gdk_root);
-}
-
-gboolean
-_gdk_quartz_display_has_pending (GdkDisplay *display)
-{
-  return (_gdk_event_queue_find_first (display) ||
-         (_gdk_quartz_event_loop_check_pending ()));
-}
-
-void
-_gdk_quartz_events_break_all_grabs (guint32 time)
-{
-  GList *devices = NULL, *l;
-  GdkSeat *seat;
-
-  seat = gdk_display_get_default_seat (_gdk_display);
-
-  devices = g_list_prepend (devices, gdk_seat_get_keyboard (seat));
-  devices = g_list_prepend (devices, gdk_seat_get_pointer (seat));
-
-  for (l = devices; l; l = l->next)
-    {
-      GdkDeviceGrabInfo *grab;
-
-      grab = _gdk_display_get_last_device_grab (_gdk_display, l->data);
-      if (grab)
-        {
-          grab->serial_end = 0;
-          grab->implicit_ungrab = TRUE;
-        }
-
-      _gdk_display_device_grab_update (_gdk_display, l->data, NULL, 0);
-    }
-
-  g_list_free (devices);
-}
-
-static void
-fixup_event (GdkEvent *event)
-{
-  if (event->any.surface)
-    g_object_ref (event->any.surface);
-  if (((event->any.type == GDK_ENTER_NOTIFY) ||
-       (event->any.type == GDK_LEAVE_NOTIFY)) &&
-      (event->crossing.child_window != NULL))
-    g_object_ref (event->crossing.child_window);
-  event->any.send_event = FALSE;
-}
-
-static void
-append_event (GdkEvent *event,
-              gboolean  windowing)
-{
-  GList *node;
-
-  fixup_event (event);
-  node = _gdk_event_queue_append (_gdk_display, event);
-
-  if (windowing)
-    _gdk_windowing_got_event (_gdk_display, node, event, 0);
-}
-
-static gint
-gdk_event_apply_filters (NSEvent *nsevent,
-                        GdkEvent *event,
-                        GList **filters)
-{
-  GList *tmp_list;
-  GdkFilterReturn result;
-  
-  tmp_list = *filters;
-
-  while (tmp_list)
-    {
-      GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data;
-      GList *node;
-
-      if ((filter->flags & GDK_EVENT_FILTER_REMOVED) != 0)
-        {
-          tmp_list = tmp_list->next;
-          continue;
-        }
-
-      filter->ref_count++;
-      result = filter->function (nsevent, event, filter->data);
-
-      /* get the next node after running the function since the
-         function may add or remove a next node */
-      node = tmp_list;
-      tmp_list = tmp_list->next;
-
-      filter->ref_count--;
-      if (filter->ref_count == 0)
-        {
-          *filters = g_list_remove_link (*filters, node);
-          g_list_free_1 (node);
-          g_free (filter);
-        }
-
-      if (result !=  GDK_FILTER_CONTINUE)
-       return result;
-    }
-
-  return GDK_FILTER_CONTINUE;
-}
-
-static guint32
-get_time_from_ns_event (NSEvent *event)
-{
-  double time = [event timestamp];
-
-  /* cast via double->uint64 conversion to make sure that it is
-   * wrapped on 32-bit machines when it overflows
-   */
-  return (guint32) (guint64) (time * 1000.0);
-}
-
-static int
-get_mouse_button_from_ns_event (NSEvent *event)
-{
-  NSInteger button;
-
-  button = [event buttonNumber];
-
-  switch (button)
-    {
-    case 0:
-      return 1;
-    case 1:
-      return 3;
-    case 2:
-      return 2;
-    default:
-      return button + 1;
-    }
-}
-
-static GdkModifierType
-get_mouse_button_modifiers_from_ns_buttons (NSUInteger nsbuttons)
-{
-  GdkModifierType modifiers = 0;
-
-  if (nsbuttons & (1 << 0))
-    modifiers |= GDK_BUTTON1_MASK;
-  if (nsbuttons & (1 << 1))
-    modifiers |= GDK_BUTTON3_MASK;
-  if (nsbuttons & (1 << 2))
-    modifiers |= GDK_BUTTON2_MASK;
-  if (nsbuttons & (1 << 3))
-    modifiers |= GDK_BUTTON4_MASK;
-  if (nsbuttons & (1 << 4))
-    modifiers |= GDK_BUTTON5_MASK;
-
-  return modifiers;
-}
-
-static GdkModifierType
-get_mouse_button_modifiers_from_ns_event (NSEvent *event)
-{
-  int button;
-  GdkModifierType state = 0;
-
-  /* This maps buttons 1 to 5 to GDK_BUTTON[1-5]_MASK */
-  button = get_mouse_button_from_ns_event (event);
-  if (button >= 1 && button <= 5)
-    state = (1 << (button + 7));
-
-  return state;
-}
-
-static GdkModifierType
-get_keyboard_modifiers_from_ns_flags (NSUInteger nsflags)
-{
-  GdkModifierType modifiers = 0;
-
-  if (nsflags & NSAlphaShiftKeyMask)
-    modifiers |= GDK_LOCK_MASK;
-  if (nsflags & NSShiftKeyMask)
-    modifiers |= GDK_SHIFT_MASK;
-  if (nsflags & NSControlKeyMask)
-    modifiers |= GDK_CONTROL_MASK;
-  if (nsflags & NSAlternateKeyMask)
-    modifiers |= GDK_ALT_MASK;
-  if (nsflags & NSCommandKeyMask)
-    modifiers |= GDK_MOD2_MASK;
-
-  return modifiers;
-}
-
-static GdkModifierType
-get_keyboard_modifiers_from_ns_event (NSEvent *nsevent)
-{
-  return get_keyboard_modifiers_from_ns_flags ([nsevent modifierFlags]);
-}
-
-/* Return an event mask from an NSEvent */
-static GdkEventMask
-get_event_mask_from_ns_event (NSEvent *nsevent)
-{
-  switch ([nsevent type])
-    {
-    case NSLeftMouseDown:
-    case NSRightMouseDown:
-    case NSOtherMouseDown:
-      return GDK_BUTTON_PRESS_MASK;
-    case NSLeftMouseUp:
-    case NSRightMouseUp:
-    case NSOtherMouseUp:
-      return GDK_BUTTON_RELEASE_MASK;
-    case NSMouseMoved:
-      return GDK_POINTER_MOTION_MASK;
-    case NSScrollWheel:
-      /* Since applications that want button press events can get
-       * scroll events on X11 (since scroll wheel events are really
-       * button press events there), we need to use GDK_BUTTON_PRESS_MASK too.
-       */
-      return GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK;
-    case NSLeftMouseDragged:
-      return (GDK_POINTER_MOTION_MASK |
-             GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK | 
-             GDK_BUTTON1_MASK);
-    case NSRightMouseDragged:
-      return (GDK_POINTER_MOTION_MASK |
-             GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK | 
-             GDK_BUTTON3_MASK);
-    case NSOtherMouseDragged:
-      {
-       GdkEventMask mask;
-
-       mask = (GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK);
-
-       if (get_mouse_button_from_ns_event (nsevent) == 2)
-         mask |= (GDK_BUTTON2_MOTION_MASK | GDK_BUTTON2_MOTION_MASK | 
-                  GDK_BUTTON2_MASK);
-
-       return mask;
-      }
-    case NSEventTypeMagnify:
-    case NSEventTypeRotate:
-      return GDK_TOUCHPAD_GESTURE_MASK;
-    case NSKeyDown:
-    case NSKeyUp:
-    case NSFlagsChanged:
-      {
-        switch (_gdk_quartz_keys_event_type (nsevent))
-         {
-         case GDK_KEY_PRESS:
-           return GDK_KEY_PRESS_MASK;
-         case GDK_KEY_RELEASE:
-           return GDK_KEY_RELEASE_MASK;
-         case GDK_NOTHING:
-           return 0;
-         default:
-           g_assert_not_reached ();
-         }
-      }
-      break;
-
-    case NSMouseEntered:
-      return GDK_ENTER_NOTIFY_MASK;
-
-    case NSMouseExited:
-      return GDK_LEAVE_NOTIFY_MASK;
-
-    default:
-      g_assert_not_reached ();
-    }
-
-  return 0;
-}
-
-static void
-get_window_point_from_screen_point (GdkSurface *window,
-                                    NSPoint    screen_point,
-                                    gint      *x,
-                                    gint      *y)
-{
-  NSPoint point;
-  NSWindow *nswindow;
-
-  nswindow = ((GdkSurfaceImplQuartz *)window->impl)->toplevel;
-
-  point = [nswindow convertScreenToBase:screen_point];
-
-  *x = point.x;
-  *y = window->height - point.y;
-}
-
-static gboolean
-is_mouse_button_press_event (NSEventType type)
-{
-  switch (type)
-    {
-      case NSLeftMouseDown:
-      case NSRightMouseDown:
-      case NSOtherMouseDown:
-        return TRUE;
-    }
-
-  return FALSE;
-}
-
-static GdkSurface *
-get_toplevel_from_ns_event (NSEvent *nsevent,
-                            NSPoint *screen_point,
-                            gint    *x,
-                            gint    *y)
-{
-  GdkSurface *toplevel = NULL;
-
-  if ([nsevent window])
-    {
-      GdkQuartzView *view;
-      NSPoint point, view_point;
-      NSRect view_frame;
-
-      view = (GdkQuartzView *)[[nsevent window] contentView];
-
-      toplevel = [view gdkSurface];
-
-      point = [nsevent locationInWindow];
-      view_point = [view convertPoint:point fromView:nil];
-      view_frame = [view frame];
-
-      /* NSEvents come in with a window set, but with window coordinates
-       * out of window bounds. For e.g. moved events this is fine, we use
-       * this information to properly handle enter/leave notify and motion
-       * events. For mouse button press/release, we want to avoid forwarding
-       * these events however, because the window they relate to is not the
-       * window set in the event. This situation appears to occur when button
-       * presses come in just before (or just after?) a window is resized and
-       * also when a button press occurs on the OS X window titlebar.
-       *
-       * By setting toplevel to NULL, we do another attempt to get the right
-       * toplevel window below.
-       */
-      if (is_mouse_button_press_event ([nsevent type]) &&
-          (view_point.x < view_frame.origin.x ||
-           view_point.x >= view_frame.origin.x + view_frame.size.width ||
-           view_point.y < view_frame.origin.y ||
-           view_point.y >= view_frame.origin.y + view_frame.size.height))
-        {
-          toplevel = NULL;
-
-          /* This is a hack for button presses to break all grabs. E.g. if
-           * a menu is open and one clicks on the title bar (or anywhere
-           * out of window bounds), we really want to pop down the menu (by
-           * breaking the grabs) before OS X handles the action of the title
-           * bar button.
-           *
-           * Because we cannot ingest this event into GDK, we have to do it
-           * here, not very nice.
-           */
-          _gdk_quartz_events_break_all_grabs (get_time_from_ns_event (nsevent));
-        }
-      else
-        {
-          *screen_point = [[nsevent window] convertBaseToScreen:point];
-
-          *x = point.x;
-          *y = toplevel->height - point.y;
-        }
-    }
-
-  if (!toplevel)
-    {
-      /* Fallback used when no NSWindow set.  This happens e.g. when
-       * we allow motion events without a window set in gdk_event_translate()
-       * that occur immediately after the main menu bar was clicked/used.
-       * This fallback will not return coordinates contained in a window's
-       * titlebar.
-       */
-      *screen_point = [NSEvent mouseLocation];
-      toplevel = find_toplevel_under_pointer (_gdk_display,
-                                              *screen_point,
-                                              x, y);
-    }
-
-  return toplevel;
-}
-
-static GdkEvent *
-create_focus_event (GdkSurface *window,
-                   gboolean   in)
-{
-  GdkEvent *event;
-  GdkQuartzDeviceManagerCore *device_manager;
-
-  event = gdk_event_new (GDK_FOCUS_CHANGE);
-  event->focus_change.window = window;
-  event->focus_change.in = in;
-
-  device_manager = GDK_QUARTZ_DEVICE_MANAGER_CORE (_gdk_device_manager);
-  gdk_event_set_device (event, device_manager->core_keyboard);
-  gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_keyboard));
-
-  return event;
-}
-
-
-static void
-generate_motion_event (GdkSurface *window)
-{
-  NSPoint screen_point;
-  GdkEvent *event;
-  gint x, y, x_root, y_root;
-  GdkQuartzDeviceManagerCore *device_manager;
-
-  event = gdk_event_new (GDK_MOTION_NOTIFY);
-  event->any.surface = NULL;
-  event->any.send_event = TRUE;
-
-  screen_point = [NSEvent mouseLocation];
-
-  _gdk_quartz_surface_nspoint_to_gdk_xy (screen_point, &x_root, &y_root);
-  get_window_point_from_screen_point (window, screen_point, &x, &y);
-
-  event->any.type = GDK_MOTION_NOTIFY;
-  event->motion.window = window;
-  event->motion.time = get_time_from_ns_event ([NSApp currentEvent]);
-  event->motion.x = x;
-  event->motion.y = y;
-  event->motion.x_root = x_root;
-  event->motion.y_root = y_root;
-  /* FIXME event->axes */
-  event->motion.state = _gdk_quartz_events_get_current_keyboard_modifiers () |
-                        _gdk_quartz_events_get_current_mouse_modifiers ();
-  device_manager = GDK_QUARTZ_DEVICE_MANAGER_CORE (_gdk_device_manager);
-  event->motion.device = device_manager->core_pointer;
-  gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_pointer));
-
-  append_event (event, TRUE);
-}
-
-/* Note: Used to both set a new focus window and to unset the old one. */
-void
-_gdk_quartz_events_update_focus_window (GdkSurface *window,
-                                       gboolean   got_focus)
-{
-  GdkEvent *event;
-
-  if (got_focus && window == current_keyboard_window)
-    return;
-
-  /* FIXME: Don't do this when grabbed? Or make GdkQuartzNSWindow
-   * disallow it in the first place instead?
-   */
-  
-  if (!got_focus && window == current_keyboard_window)
-    {
-      event = create_focus_event (current_keyboard_window, FALSE);
-      append_event (event, FALSE);
-      g_object_unref (current_keyboard_window);
-      current_keyboard_window = NULL;
-    }
-
-  if (got_focus)
-    {
-      if (current_keyboard_window)
-       {
-         event = create_focus_event (current_keyboard_window, FALSE);
-         append_event (event, FALSE);
-         g_object_unref (current_keyboard_window);
-         current_keyboard_window = NULL;
-       }
-      
-      event = create_focus_event (window, TRUE);
-      append_event (event, FALSE);
-      current_keyboard_window = g_object_ref (window);
-
-      /* We just became the active window.  Unlike X11, Mac OS X does
-       * not send us motion events while the window does not have focus
-       * ("is not key").  We send a dummy motion notify event now, so that
-       * everything in the window is set to correct state.
-       */
-      generate_motion_event (window);
-    }
-}
-
-void
-_gdk_quartz_events_send_map_event (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (!impl->toplevel)
-    return;
-
-  if (window->event_mask & GDK_STRUCTURE_MASK)
-    {
-      GdkEvent event;
-
-      event.any.type = GDK_MAP;
-      event.any.surface = window;
-  
-      gdk_event_put (&event);
-    }
-}
-
-static GdkSurface *
-find_toplevel_under_pointer (GdkDisplay *display,
-                             NSPoint     screen_point,
-                             gint       *x,
-                             gint       *y)
-{
-  GdkSurface *toplevel;
-  GdkPointerSurfaceInfo *info;
-
-  info = _gdk_display_get_pointer_info (display, GDK_QUARTZ_DEVICE_MANAGER_CORE (_gdk_device_manager)->core_pointer);
-  toplevel = info->toplevel_under_pointer;
-  if (toplevel && SURFACE_IS_TOPLEVEL (toplevel))
-    get_window_point_from_screen_point (toplevel, screen_point, x, y);
-
-  if (toplevel)
-    {
-      /* If the coordinates are out of window bounds, this toplevel is not
-       * under the pointer and we thus return NULL. This can occur when
-       * toplevel under pointer has not yet been updated due to a very recent
-       * window resize. Alternatively, we should no longer be relying on
-       * the toplevel_under_pointer value which is maintained in gdksurface.c.
-       */
-      if (*x < 0 || *y < 0 || *x >= toplevel->width || *y >= toplevel->height)
-        return NULL;
-    }
-
-  return toplevel;
-}
-
-static GdkSurface *
-find_toplevel_for_keyboard_event (NSEvent *nsevent)
-{
-  GList *devices = NULL, *l;
-  GdkSurface *window;
-  GdkDisplay *display;
-  GdkQuartzView *view;
-  GdkSeat *seat;
-
-  view = (GdkQuartzView *)[[nsevent window] contentView];
-  window = [view gdkSurface];
-
-  display = gdk_surface_get_display (window);
-
-  seat = gdk_display_get_default_seat (display);
-
-  devices = g_list_prepend (devices, gdk_seat_get_keyboard (seat));
-  devices = g_list_prepend (devices, gdk_seat_get_pointer (seat));
-
-  for (l = devices; l; l = l->next)
-    {
-      GdkDeviceGrabInfo *grab;
-      GdkDevice *device = l->data;
-
-      if (gdk_device_get_source(device) != GDK_SOURCE_KEYBOARD)
-        continue;
-
-      grab = _gdk_display_get_last_device_grab (display, device);
-      if (grab && grab->window && !grab->owner_events)
-        {
-          window = gdk_surface_get_toplevel (grab->window);
-          break;
-        }
-    }
-
-  g_list_free (devices);
-
-  return window;
-}
-
-static GdkSurface *
-find_toplevel_for_mouse_event (NSEvent    *nsevent,
-                               gint       *x,
-                               gint       *y)
-{
-  NSPoint screen_point;
-  NSEventType event_type;
-  GdkSurface *toplevel;
-  GdkDisplay *display;
-  GdkDeviceGrabInfo *grab;
-
-  toplevel = get_toplevel_from_ns_event (nsevent, &screen_point, x, y);
-
-  display = gdk_surface_get_display (toplevel);
-
-  event_type = [nsevent type];
-
-  /* From the docs for XGrabPointer:
-   *
-   * If owner_events is True and if a generated pointer event
-   * would normally be reported to this client, it is reported
-   * as usual. Otherwise, the event is reported with respect to
-   * the grab_window and is reported only if selected by
-   * event_mask. For either value of owner_events, unreported
-   * events are discarded.
-   */
-  grab = _gdk_display_get_last_device_grab (display,
-                                            GDK_QUARTZ_DEVICE_MANAGER_CORE (_gdk_device_manager)->core_pointer);
-  if (SURFACE_IS_TOPLEVEL (toplevel) && grab)
-    {
-      /* Implicit grabs do not go through XGrabPointer and thus the
-       * event mask should not be checked.
-       */
-      if (!grab->implicit
-          && (grab->event_mask & get_event_mask_from_ns_event (nsevent)) == 0)
-        return NULL;
-
-      if (grab->owner_events)
-        {
-          /* For owner events, we need to use the toplevel under the
-           * pointer, not the window from the NSEvent, since that is
-           * reported with respect to the key window, which could be
-           * wrong.
-           */
-          GdkSurface *toplevel_under_pointer;
-          gint x_tmp, y_tmp;
-
-          toplevel_under_pointer = find_toplevel_under_pointer (display,
-                                                                screen_point,
-                                                                &x_tmp, &y_tmp);
-          if (toplevel_under_pointer)
-            {
-              toplevel = toplevel_under_pointer;
-              *x = x_tmp;
-              *y = y_tmp;
-            }
-
-          return toplevel;
-        }
-      else
-        {
-          /* Finally check the grab window. */
-          GdkSurface *grab_toplevel;
-
-          grab_toplevel = gdk_surface_get_toplevel (grab->window);
-          get_window_point_from_screen_point (grab_toplevel, screen_point,
-                                              x, y);
-
-          return grab_toplevel;
-        }
-
-      return NULL;
-    }
-  else 
-    {
-      /* The non-grabbed case. */
-      GdkSurface *toplevel_under_pointer;
-      gint x_tmp, y_tmp;
-
-      /* Ignore all events but mouse moved that might be on the title
-       * bar (above the content view). The reason is that otherwise
-       * gdk gets confused about getting e.g. button presses with no
-       * window (the title bar is not known to it).
-       */
-      if (event_type != NSMouseMoved)
-        if (*y < 0)
-          return NULL;
-
-      /* As for owner events, we need to use the toplevel under the
-       * pointer, not the window from the NSEvent.
-       */
-      toplevel_under_pointer = find_toplevel_under_pointer (display,
-                                                            screen_point,
-                                                            &x_tmp, &y_tmp);
-      if (toplevel_under_pointer
-          && SURFACE_IS_TOPLEVEL (toplevel_under_pointer))
-        {
-          GdkSurfaceImplQuartz *toplevel_impl;
-
-          toplevel = toplevel_under_pointer;
-
-          toplevel_impl = (GdkSurfaceImplQuartz *)toplevel->impl;
-
-          *x = x_tmp;
-          *y = y_tmp;
-        }
-
-      return toplevel;
-    }
-
-  return NULL;
-}
-
-/* This function finds the correct window to send an event to, taking
- * into account grabs, event propagation, and event masks.
- */
-static GdkSurface *
-find_window_for_ns_event (NSEvent *nsevent, 
-                          gint    *x, 
-                          gint    *y,
-                          gint    *x_root,
-                          gint    *y_root)
-{
-  GdkQuartzView *view;
-  GdkSurface *toplevel;
-  NSPoint screen_point;
-  NSEventType event_type;
-
-  view = (GdkQuartzView *)[[nsevent window] contentView];
-
-  toplevel = get_toplevel_from_ns_event (nsevent, &screen_point, x, y);
-  if (!toplevel)
-    return NULL;
-  _gdk_quartz_surface_nspoint_to_gdk_xy (screen_point, x_root, y_root);
-
-  event_type = [nsevent type];
-
-  switch (event_type)
-    {
-    case NSLeftMouseDown:
-    case NSRightMouseDown:
-    case NSOtherMouseDown:
-    case NSLeftMouseUp:
-    case NSRightMouseUp:
-    case NSOtherMouseUp:
-    case NSMouseMoved:
-    case NSScrollWheel:
-    case NSLeftMouseDragged:
-    case NSRightMouseDragged:
-    case NSOtherMouseDragged:
-    case NSEventTypeMagnify:
-    case NSEventTypeRotate:
-      return find_toplevel_for_mouse_event (nsevent, x, y);
-      
-    case NSMouseEntered:
-    case NSMouseExited:
-      /* Only handle our own entered/exited events, not the ones for the
-       * titlebar buttons.
-       */
-      if ([view trackingRect] == [nsevent trackingNumber])
-        return toplevel;
-      else
-        return NULL;
-
-    case NSKeyDown:
-    case NSKeyUp:
-    case NSFlagsChanged:
-      return find_toplevel_for_keyboard_event (nsevent);
-
-    default:
-      /* Ignore everything else. */
-      break;
-    }
-
-  return NULL;
-}
-
-static void
-fill_crossing_event (GdkSurface       *toplevel,
-                     GdkEvent        *event,
-                     NSEvent         *nsevent,
-                     gint             x,
-                     gint             y,
-                     gint             x_root,
-                     gint             y_root,
-                     GdkEventType     event_type,
-                     GdkCrossingMode  mode,
-                     GdkNotifyType    detail)
-{
-  GdkQuartzDeviceManagerCore *device_manager;
-
-  event->any.type = event_type;
-  event->crossing.window = toplevel;
-  event->crossing.child_window = NULL;
-  event->crossing.time = get_time_from_ns_event (nsevent);
-  event->crossing.x = x;
-  event->crossing.y = y;
-  event->crossing.x_root = x_root;
-  event->crossing.y_root = y_root;
-  event->crossing.mode = mode;
-  event->crossing.detail = detail;
-  event->crossing.state = get_keyboard_modifiers_from_ns_event (nsevent) |
-                         _gdk_quartz_events_get_current_mouse_modifiers ();
-
-  device_manager = GDK_QUARTZ_DEVICE_MANAGER_CORE (_gdk_device_manager);
-  gdk_event_set_device (event, device_manager->core_pointer);
-  gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_pointer));
-
-  /* FIXME: Focus and button state? */
-}
-
-/* fill_pinch_event handles the conversion from the two OSX gesture events
-   NSEventTypeMagnfiy and NSEventTypeRotate to the GDK_TOUCHPAD_PINCH event.
-   The normal behavior of the OSX events is that they produce as sequence of
-     1 x NSEventPhaseBegan,
-     n x NSEventPhaseChanged,
-     1 x NSEventPhaseEnded
-   This can happen for both the Magnify and the Rotate events independently.
-   As both events are summarized in one GDK_TOUCHPAD_PINCH event sequence, a
-   little state machine handles the case of two NSEventPhaseBegan events in
-   a sequence, e.g. Magnify(Began), Magnify(Changed)..., Rotate(Began)...
-   such that PINCH(STARTED), PINCH(UPDATE).... will not show a second
-   PINCH(STARTED) event.
-*/
-#ifdef AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER
-static void
-fill_pinch_event (GdkSurface *window,
-                  GdkEvent  *event,
-                  NSEvent   *nsevent,
-                  gint       x,
-                  gint       y,
-                  gint       x_root,
-                  gint       y_root)
-{
-  static double last_scale = 1.0;
-  static enum {
-    FP_STATE_IDLE,
-    FP_STATE_UPDATE
-  } last_state = FP_STATE_IDLE;
-  GdkQuartzDeviceManagerCore *device_manager;
-
-  device_manager = GDK_QUARTZ_DEVICE_MANAGER_CORE (_gdk_device_manager);
-
-  event->any.type = GDK_TOUCHPAD_PINCH;
-  event->touchpad_pinch.window = window;
-  event->touchpad_pinch.time = get_time_from_ns_event (nsevent);
-  event->touchpad_pinch.x = x;
-  event->touchpad_pinch.y = y;
-  event->touchpad_pinch.x_root = x_root;
-  event->touchpad_pinch.y_root = y_root;
-  event->touchpad_pinch.state = get_keyboard_modifiers_from_ns_event (nsevent);
-  event->touchpad_pinch.n_fingers = 2;
-  event->touchpad_pinch.dx = 0.0;
-  event->touchpad_pinch.dy = 0.0;
-  gdk_event_set_device (event, device_manager->core_pointer);
-
-  switch ([nsevent phase])
-    {
-    case NSEventPhaseBegan:
-      switch (last_state)
-        {
-        case FP_STATE_IDLE:
-          event->touchpad_pinch.phase = GDK_TOUCHPAD_GESTURE_PHASE_BEGIN;
-          last_state = FP_STATE_UPDATE;
-          last_scale = 1.0;
-          break;
-        case FP_STATE_UPDATE:
-          /* We have already received a PhaseBegan event but no PhaseEnded
-             event. This can happen, e.g. Magnify(Began), Magnify(Change)...
-             Rotate(Began), Rotate (Change),...., Magnify(End) Rotate(End)
-          */
-          event->touchpad_pinch.phase = GDK_TOUCHPAD_GESTURE_PHASE_UPDATE;
-          break;
-        }
-      break;
-    case NSEventPhaseChanged:
-      event->touchpad_pinch.phase = GDK_TOUCHPAD_GESTURE_PHASE_UPDATE;
-      break;
-    case NSEventPhaseEnded:
-      event->touchpad_pinch.phase = GDK_TOUCHPAD_GESTURE_PHASE_END;
-      switch (last_state)
-        {
-        case FP_STATE_IDLE:
-          /* We are idle but have received a second PhaseEnded event.
-             This can happen because we have Magnify and Rotate OSX
-             event sequences. We just send a second end GDK_PHASE_END.
-          */
-          break;
-        case FP_STATE_UPDATE:
-          last_state = FP_STATE_IDLE;
-          break;
-        }
-      break;
-    case NSEventPhaseCancelled:
-      event->touchpad_pinch.phase = GDK_TOUCHPAD_GESTURE_PHASE_CANCEL;
-      last_state = FP_STATE_IDLE;
-      break;
-    case NSEventPhaseMayBegin:
-    case NSEventPhaseStationary:
-      event->touchpad_pinch.phase = GDK_TOUCHPAD_GESTURE_PHASE_CANCEL;
-      break;
-    default:
-      g_assert_not_reached ();
-      break;
-    }
-
-  switch ([nsevent type])
-    {
-    case NSEventTypeMagnify:
-      last_scale *= [nsevent magnification] + 1.0;
-      event->touchpad_pinch.angle_delta = 0.0;
-      break;
-    case NSEventTypeRotate:
-      event->touchpad_pinch.angle_delta = - [nsevent rotation] * G_PI / 180.0;
-      break;
-    default:
-      g_assert_not_reached ();
-    }
-  event->touchpad_pinch.scale = last_scale;
-}
-#endif /* OSX Version >= 10.8 */
-
-static void
-fill_button_event (GdkSurface *window,
-                   GdkEvent  *event,
-                   NSEvent   *nsevent,
-                   gint       x,
-                   gint       y,
-                   gint       x_root,
-                   gint       y_root)
-{
-  GdkEventType type;
-  gint state;
-  GdkQuartzDeviceManagerCore *device_manager;
-
-  state = get_keyboard_modifiers_from_ns_event (nsevent) |
-         _gdk_quartz_events_get_current_mouse_modifiers ();
-
-  switch ([nsevent type])
-    {
-    case NSLeftMouseDown:
-    case NSRightMouseDown:
-    case NSOtherMouseDown:
-      type = GDK_BUTTON_PRESS;
-      state &= ~get_mouse_button_modifiers_from_ns_event (nsevent);
-      break;
-
-    case NSLeftMouseUp:
-    case NSRightMouseUp:
-    case NSOtherMouseUp:
-      type = GDK_BUTTON_RELEASE;
-      state |= get_mouse_button_modifiers_from_ns_event (nsevent);
-      break;
-
-    default:
-      g_assert_not_reached ();
-    }
-
-  event->any.type = type;
-  event->button.window = window;
-  event->button.time = get_time_from_ns_event (nsevent);
-  event->button.x = x;
-  event->button.y = y;
-  event->button.x_root = x_root;
-  event->button.y_root = y_root;
-  /* FIXME event->axes */
-  event->button.state = state;
-  event->button.button = get_mouse_button_from_ns_event (nsevent);
-  device_manager = GDK_QUARTZ_DEVICE_MANAGER_CORE (_gdk_device_manager);
-  event->button.device = device_manager->core_pointer;
-  gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_pointer));
-}
-
-static void
-fill_motion_event (GdkSurface *window,
-                   GdkEvent  *event,
-                   NSEvent   *nsevent,
-                   gint       x,
-                   gint       y,
-                   gint       x_root,
-                   gint       y_root)
-{
-  GdkQuartzDeviceManagerCore *device_manager;
-
-  event->any.type = GDK_MOTION_NOTIFY;
-  event->motion.window = window;
-  event->motion.time = get_time_from_ns_event (nsevent);
-  event->motion.x = x;
-  event->motion.y = y;
-  event->motion.x_root = x_root;
-  event->motion.y_root = y_root;
-  /* FIXME event->axes */
-  event->motion.state = get_keyboard_modifiers_from_ns_event (nsevent) |
-                        _gdk_quartz_events_get_current_mouse_modifiers ();
-  device_manager = GDK_QUARTZ_DEVICE_MANAGER_CORE (_gdk_device_manager);
-  event->motion.device = device_manager->core_pointer;
-  gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_pointer));
-}
-
-static void
-fill_scroll_event (GdkSurface          *window,
-                   GdkEvent           *event,
-                   NSEvent            *nsevent,
-                   gint                x,
-                   gint                y,
-                   gint                x_root,
-                   gint                y_root,
-                   gdouble             delta_x,
-                   gdouble             delta_y,
-                   GdkScrollDirection  direction)
-{
-  GdkQuartzDeviceManagerCore *device_manager;
-  NSPoint point;
-
-  point = [nsevent locationInWindow];
-  device_manager = GDK_QUARTZ_DEVICE_MANAGER_CORE (_gdk_device_manager);
-
-  event->any.type = GDK_SCROLL;
-  event->scroll.window = window;
-  event->scroll.time = get_time_from_ns_event (nsevent);
-  event->scroll.x = x;
-  event->scroll.y = y;
-  event->scroll.x_root = x_root;
-  event->scroll.y_root = y_root;
-  event->scroll.state = get_keyboard_modifiers_from_ns_event (nsevent);
-  event->scroll.direction = direction;
-  event->scroll.device = device_manager->core_pointer;
-  event->scroll.delta_x = delta_x;
-  event->scroll.delta_y = delta_y;
-  gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_pointer));
-}
-
-static void
-fill_key_event (GdkSurface    *window,
-                GdkEvent     *event,
-                NSEvent      *nsevent,
-                GdkEventType  type)
-{
-  GdkEventPrivate *priv;
-  GdkQuartzDeviceManagerCore *device_manager;
-
-  priv = (GdkEventPrivate *) event;
-  priv->windowing_data = [nsevent retain];
-
-  event->any.type = type;
-  event->key.window = window;
-  event->key.time = get_time_from_ns_event (nsevent);
-  event->key.state = get_keyboard_modifiers_from_ns_event (nsevent);
-  event->key.hardware_keycode = [nsevent keyCode];
-  gdk_event_set_scancode (event, [nsevent keyCode]);
-  event->key.group = ([nsevent modifierFlags] & NSAlternateKeyMask) ? 1 : 0;
-  event->key.keyval = GDK_KEY_VoidSymbol;
-
-  device_manager = GDK_QUARTZ_DEVICE_MANAGER_CORE (_gdk_device_manager);
-  gdk_event_set_device (event, device_manager->core_keyboard);
-  gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_keyboard));
-  
-  gdk_keymap_translate_keyboard_state (gdk_display_get_keymap (_gdk_display),
-                                      event->key.hardware_keycode,
-                                      event->key.state, 
-                                      event->key.group,
-                                      &event->key.keyval,
-                                      NULL, NULL, NULL);
-
-  event->key.is_modifier = _gdk_quartz_keys_is_modifier (event->key.hardware_keycode);
-
-  /* If the key press is a modifier, the state should include the mask
-   * for that modifier but only for releases, not presses. This
-   * matches the X11 backend behavior.
-   */
-  if (event->key.is_modifier)
-    {
-      int mask = 0;
-
-      switch (event->key.keyval)
-        {
-        case GDK_KEY_Meta_R:
-        case GDK_KEY_Meta_L:
-          mask = GDK_MOD2_MASK;
-          break;
-        case GDK_KEY_Shift_R:
-        case GDK_KEY_Shift_L:
-          mask = GDK_SHIFT_MASK;
-          break;
-        case GDK_KEY_Caps_Lock:
-          mask = GDK_LOCK_MASK;
-          break;
-        case GDK_KEY_Alt_R:
-        case GDK_KEY_Alt_L:
-          mask = GDK_ALT_MASK;
-          break;
-        case GDK_KEY_Control_R:
-        case GDK_KEY_Control_L:
-          mask = GDK_CONTROL_MASK;
-          break;
-        default:
-          mask = 0;
-        }
-
-      if (type == GDK_KEY_PRESS)
-        event->key.state &= ~mask;
-      else if (type == GDK_KEY_RELEASE)
-        event->key.state |= mask;
-    }
-
-  event->key.state |= _gdk_quartz_events_get_current_mouse_modifiers ();
-
-  /* The X11 backend adds the first virtual modifier MOD2..MOD5 are
-   * mapped to. Since we only have one virtual modifier in the quartz
-   * backend, calling the standard function will do.
-   */
-  gdk_keymap_add_virtual_modifiers (gdk_display_get_keymap (_gdk_display),
-                                    &event->key.state);
-
-  GDK_NOTE(EVENTS,
-    g_message ("key %s:\t\twindow: %p  key: %12s  %d",
-         type == GDK_KEY_PRESS ? "press" : "release",
-         event->key.window,
-         event->key.keyval ? gdk_keyval_name (event->key.keyval) : "(none)",
-         event->key.keyval));
-}
-
-static gboolean
-synthesize_crossing_event (GdkSurface *window,
-                           GdkEvent  *event,
-                           NSEvent   *nsevent,
-                           gint       x,
-                           gint       y,
-                           gint       x_root,
-                           gint       y_root)
-{
-  switch ([nsevent type])
-    {
-    case NSMouseEntered:
-      /* Enter events are considered always to be from another toplevel
-       * window, this shouldn't negatively affect any app or gtk code,
-       * and is the only way to make GtkMenu work. EEK EEK EEK.
-       */
-      if (!(window->event_mask & GDK_ENTER_NOTIFY_MASK))
-        return FALSE;
-
-      fill_crossing_event (window, event, nsevent,
-                           x, y,
-                           x_root, y_root,
-                           GDK_ENTER_NOTIFY,
-                           GDK_CROSSING_NORMAL,
-                           GDK_NOTIFY_NONLINEAR);
-      return TRUE;
-
-    case NSMouseExited:
-      /* See above */
-      if (!(window->event_mask & GDK_LEAVE_NOTIFY_MASK))
-        return FALSE;
-
-      fill_crossing_event (window, event, nsevent,
-                           x, y,
-                           x_root, y_root,
-                           GDK_LEAVE_NOTIFY,
-                           GDK_CROSSING_NORMAL,
-                           GDK_NOTIFY_NONLINEAR);
-      return TRUE;
-
-    default:
-      break;
-    }
-
-  return FALSE;
-}
-
-void
-_gdk_quartz_synthesize_null_key_event (GdkSurface *window)
-{
-  GdkEvent *event;
-  GdkQuartzDeviceManagerCore *device_manager;
-
-  event = gdk_event_new (GDK_KEY_PRESS);
-  event->any.type = GDK_KEY_PRESS;
-  event->key.window = window;
-  event->key.state = 0;
-  event->key.hardware_keycode = 0;
-  event->key.group = 0;
-  event->key.keyval = GDK_KEY_VoidSymbol;
-  device_manager = GDK_QUARTZ_DEVICE_MANAGER_CORE (_gdk_device_manager);
-  gdk_event_set_device (event, device_manager->core_keyboard);
-  gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_keyboard));
-  append_event(event, FALSE);
-}
-
-GdkModifierType
-_gdk_quartz_events_get_current_keyboard_modifiers (void)
-{
-  if (gdk_quartz_osx_version () >= GDK_OSX_SNOW_LEOPARD)
-    {
-      return get_keyboard_modifiers_from_ns_flags ([NSClassFromString(@"NSEvent") modifierFlags]);
-    }
-  else
-    {
-      guint carbon_modifiers = GetCurrentKeyModifiers ();
-      GdkModifierType modifiers = 0;
-
-      if (carbon_modifiers & alphaLock)
-        modifiers |= GDK_LOCK_MASK;
-      if (carbon_modifiers & shiftKey)
-        modifiers |= GDK_SHIFT_MASK;
-      if (carbon_modifiers & controlKey)
-        modifiers |= GDK_CONTROL_MASK;
-      if (carbon_modifiers & optionKey)
-        modifiers |= GDK_ALT_MASK;
-      if (carbon_modifiers & cmdKey)
-        modifiers |= GDK_MOD2_MASK;
-
-      return modifiers;
-    }
-}
-
-GdkModifierType
-_gdk_quartz_events_get_current_mouse_modifiers (void)
-{
-  if (gdk_quartz_osx_version () >= GDK_OSX_SNOW_LEOPARD)
-    {
-      return get_mouse_button_modifiers_from_ns_buttons ([NSClassFromString(@"NSEvent") pressedMouseButtons]);
-    }
-  else
-    {
-      return get_mouse_button_modifiers_from_ns_buttons (GetCurrentButtonState ());
-    }
-}
-
-/* Detect window resizing */
-
-static gboolean
-test_resize (NSEvent *event, GdkSurface *toplevel, gint x, gint y)
-{
-  GdkSurfaceImplQuartz *toplevel_impl;
-  gboolean lion;
-
-  /* Resizing from the resize indicator only begins if an NSLeftMouseButton
-   * event is received in the resizing area.
-   */
-  toplevel_impl = (GdkSurfaceImplQuartz *)toplevel->impl;
-  if ([toplevel_impl->toplevel showsResizeIndicator])
-  if ([event type] == NSLeftMouseDown &&
-      [toplevel_impl->toplevel showsResizeIndicator])
-    {
-      NSRect frame;
-
-      /* If the resize indicator is visible and the event
-       * is in the lower right 15x15 corner, we leave these
-       * events to Cocoa as to be handled as resize events.
-       * Applications may have widgets in this area.  These
-       * will most likely be larger than 15x15 and for
-       * scroll bars there are also other means to move
-       * the scroll bar.  Since the resize indicator is
-       * the only way of resizing windows on Mac OS, it
-       * is too important to not make functional.
-       */
-      frame = [toplevel_impl->view bounds];
-      if (x > frame.size.width - GRIP_WIDTH &&
-          x < frame.size.width &&
-          y > frame.size.height - GRIP_HEIGHT &&
-          y < frame.size.height)
-        return TRUE;
-     }
-
-  /* If we're on Lion and within 5 pixels of an edge,
-   * then assume that the user wants to resize, and
-   * return NULL to let Quartz get on with it. We check
-   * the selector isRestorable to see if we're on 10.7.
-   * This extra check is in case the user starts
-   * dragging before GDK recognizes the grab.
-   *
-   * We perform this check for a button press of all buttons, because we
-   * do receive, for instance, a right mouse down event for a GDK surface
-   * for x-coordinate range [-3, 0], but we do not want to forward this
-   * into GDK. Forwarding such events into GDK will confuse the pointer
-   * window finding code, because there are no GdkSurfaces present in
-   * the range [-3, 0].
-   */
-  lion = gdk_quartz_osx_version () >= GDK_OSX_LION;
-  if (lion &&
-      ([event type] == NSLeftMouseDown ||
-       [event type] == NSRightMouseDown ||
-       [event type] == NSOtherMouseDown))
-    {
-      if (x < GDK_LION_RESIZE ||
-          x > toplevel->width - GDK_LION_RESIZE ||
-          y > toplevel->height - GDK_LION_RESIZE)
-        return TRUE;
-    }
-
-  return FALSE;
-}
-
-static gboolean
-gdk_event_translate (GdkEvent *event,
-                     NSEvent  *nsevent)
-{
-  NSEventType event_type;
-  NSWindow *nswindow;
-  GdkSurface *window;
-  int x, y;
-  int x_root, y_root;
-  gboolean return_val;
-
-  /* There is no support for real desktop wide grabs, so we break
-   * grabs when the application loses focus (gets deactivated).
-   */
-  event_type = [nsevent type];
-  if (event_type == NSAppKitDefined)
-    {
-      if ([nsevent subtype] == NSApplicationDeactivatedEventType)
-        _gdk_quartz_events_break_all_grabs (get_time_from_ns_event (nsevent));
-
-      /* This could potentially be used to break grabs when clicking
-       * on the title. The subtype 20 is undocumented so it's probably
-       * not a good idea: else if (subtype == 20) break_all_grabs ();
-       */
-
-      /* Leave all AppKit events to AppKit. */
-      return FALSE;
-    }
-
-  if (_gdk_default_filters)
-    {
-      /* Apply global filters */
-      GdkFilterReturn result;
-
-      result = gdk_event_apply_filters (nsevent, event, &_gdk_default_filters);
-      if (result != GDK_FILTER_CONTINUE)
-        {
-          return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
-          goto done;
-        }
-    }
-
-  nswindow = [nsevent window];
-
-  /* Ignore events for windows not created by GDK. */
-  if (nswindow && ![[nswindow contentView] isKindOfClass:[GdkQuartzView class]])
-    return FALSE;
-
-  /* Ignore events for ones with no windows */
-  if (!nswindow)
-    {
-      GdkSurface *toplevel = NULL;
-
-      if (event_type == NSMouseMoved)
-        {
-          /* Motion events received after clicking the menu bar do not have the
-           * window field set.  Instead of giving up on the event immediately,
-           * we first check whether this event is within our window bounds.
-           */
-          NSPoint screen_point = [NSEvent mouseLocation];
-          gint x_tmp, y_tmp;
-
-          toplevel = find_toplevel_under_pointer (_gdk_display,
-                                                  screen_point,
-                                                  &x_tmp, &y_tmp);
-        }
-
-      if (!toplevel)
-        return FALSE;
-    }
-
-  /* Ignore events and break grabs while the window is being
-   * dragged. This is a workaround for the window getting events for
-   * the window title.
-   */
-  if ([(GdkQuartzNSWindow *)nswindow isInMove])
-    {
-      _gdk_quartz_events_break_all_grabs (get_time_from_ns_event (nsevent));
-      return FALSE;
-    }
-
-  /* Also when in a manual resize or move , we ignore events so that
-   * these are pushed to GdkQuartzNSWindow's sendEvent handler.
-   */
-  if ([(GdkQuartzNSWindow *)nswindow isInManualResizeOrMove])
-    return FALSE;
-
-  /* Find the right GDK surface to send the event to, taking grabs and
-   * event masks into consideration.
-   */
-  window = find_window_for_ns_event (nsevent, &x, &y, &x_root, &y_root);
-  if (!window)
-    return FALSE;
-
-  /* Quartz handles resizing on its own, so we want to stay out of the way. */
-  if (test_resize (nsevent, window, x, y))
-    return FALSE;
-
-  /* Apply any window filters. */
-  if (GDK_IS_SURFACE (window))
-    {
-      GdkFilterReturn result;
-
-      if (window->filters)
-       {
-         g_object_ref (window);
-
-         result = gdk_event_apply_filters (nsevent, event, &window->filters);
-
-         g_object_unref (window);
-
-         if (result != GDK_FILTER_CONTINUE)
-           {
-             return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
-             goto done;
-           }
-       }
-    }
-
-  /* If the app is not active leave the event to AppKit so the window gets
-   * focused correctly and don't do click-through (so we behave like most
-   * native apps). If the app is active, we focus the window and then handle
-   * the event, also to match native apps.
-   */
-  if ((event_type == NSRightMouseDown ||
-       event_type == NSOtherMouseDown ||
-       event_type == NSLeftMouseDown))
-    {
-      GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-      if (![NSApp isActive])
-        {
-          [NSApp activateIgnoringOtherApps:YES];
-          return FALSE;
-        }
-      else if (![impl->toplevel isKeyWindow])
-        {
-          GdkDeviceGrabInfo *grab;
-
-          grab = _gdk_display_get_last_device_grab (_gdk_display,
-                                                    GDK_QUARTZ_DEVICE_MANAGER_CORE (_gdk_device_manager)->core_pointer);
-          if (!grab)
-            [impl->toplevel makeKeyWindow];
-        }
-    }
-
-  return_val = TRUE;
-
-  switch (event_type)
-    {
-    case NSLeftMouseDown:
-    case NSRightMouseDown:
-    case NSOtherMouseDown:
-    case NSLeftMouseUp:
-    case NSRightMouseUp:
-    case NSOtherMouseUp:
-      fill_button_event (window, event, nsevent, x, y, x_root, y_root);
-      break;
-
-    case NSLeftMouseDragged:
-    case NSRightMouseDragged:
-    case NSOtherMouseDragged:
-    case NSMouseMoved:
-      fill_motion_event (window, event, nsevent, x, y, x_root, y_root);
-      break;
-
-    case NSScrollWheel:
-      {
-        GdkScrollDirection direction;
-       float dx;
-       float dy;
-#ifdef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
-       if (gdk_quartz_osx_version() >= GDK_OSX_LION &&
-           [nsevent hasPreciseScrollingDeltas])
-         {
-           dx = [nsevent scrollingDeltaX];
-           dy = [nsevent scrollingDeltaY];
-            direction = GDK_SCROLL_SMOOTH;
-
-            fill_scroll_event (window, event, nsevent, x, y, x_root, y_root,
-                               -dx, -dy, direction);
-
-            /* Fall through for scroll buttons emulation */
-         }
-#endif
-        dx = [nsevent deltaX];
-        dy = [nsevent deltaY];
-
-        if (dy != 0.0)
-          {
-            if (dy < 0.0)
-              direction = GDK_SCROLL_DOWN;
-            else
-              direction = GDK_SCROLL_UP;
-
-            dy = fabs (dy);
-            dx = 0.0;
-          }
-        else if (dx != 0.0)
-          {
-            if (dx < 0.0)
-              direction = GDK_SCROLL_RIGHT;
-            else
-              direction = GDK_SCROLL_LEFT;
-
-            dx = fabs (dx);
-            dy = 0.0;
-          }
-
-        if (dx != 0.0 || dy != 0.0)
-          {
-#ifdef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
-           if (gdk_quartz_osx_version() >= GDK_OSX_LION &&
-               [nsevent hasPreciseScrollingDeltas])
-              {
-                GdkEvent *emulated_event;
-
-                emulated_event = gdk_event_new (GDK_SCROLL);
-                gdk_event_set_pointer_emulated (emulated_event, TRUE);
-                fill_scroll_event (window, emulated_event, nsevent,
-                                   x, y, x_root, y_root,
-                                   dx, dy, direction);
-                append_event (emulated_event, TRUE);
-              }
-            else
-#endif
-              fill_scroll_event (window, event, nsevent,
-                                 x, y, x_root, y_root,
-                                 dx, dy, direction);
-          }
-      }
-      break;
-#ifdef AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER
-    case NSEventTypeMagnify:
-    case NSEventTypeRotate:
-      /* Event handling requires [NSEvent phase] which was introduced in 10.7 */
-      /* However - Tests on 10.7 showed that phase property does not work     */
-      if (gdk_quartz_osx_version () >= GDK_OSX_MOUNTAIN_LION)
-        fill_pinch_event (window, event, nsevent, x, y, x_root, y_root);
-      else
-        return_val = FALSE;
-      break;
-#endif
-    case NSMouseExited:
-      if (SURFACE_IS_TOPLEVEL (window))
-          [[NSCursor arrowCursor] set];
-      /* fall through */
-    case NSMouseEntered:
-      return_val = synthesize_crossing_event (window, event, nsevent, x, y, x_root, y_root);
-      break;
-
-    case NSKeyDown:
-    case NSKeyUp:
-    case NSFlagsChanged:
-      {
-        GdkEventType type;
-
-        type = _gdk_quartz_keys_event_type (nsevent);
-        if (type == GDK_NOTHING)
-          return_val = FALSE;
-        else
-          fill_key_event (window, event, nsevent, type);
-      }
-      break;
-
-    default:
-      /* Ignore everything elsee. */
-      return_val = FALSE;
-      break;
-    }
-
- done:
-  if (return_val)
-    {
-      if (event->any.surface)
-       g_object_ref (event->any.surface);
-      if (((event->any.type == GDK_ENTER_NOTIFY) ||
-          (event->any.type == GDK_LEAVE_NOTIFY)) &&
-         (event->crossing.child_window != NULL))
-       g_object_ref (event->crossing.child_window);
-    }
-  else
-    {
-      /* Mark this event as having no resources to be freed */
-      event->any.surface = NULL;
-      event->any.type = GDK_NOTHING;
-    }
-
-  return return_val;
-}
-
-void
-_gdk_quartz_display_queue_events (GdkDisplay *display)
-{  
-  NSEvent *nsevent;
-
-  nsevent = _gdk_quartz_event_loop_get_pending ();
-  if (nsevent)
-    {
-      GdkEvent *event;
-      GList *node;
-
-      event = gdk_event_new (GDK_NOTHING);
-
-      event->any.surface = NULL;
-      event->any.send_event = FALSE;
-
-      ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
-
-      node = _gdk_event_queue_append (display, event);
-
-      if (gdk_event_translate (event, nsevent))
-        {
-         ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
-          _gdk_windowing_got_event (display, node, event, 0);
-        }
-      else
-        {
-         _gdk_event_queue_remove_link (display, node);
-         g_list_free_1 (node);
-         g_object_unref (event);
-
-          [NSApp sendEvent:nsevent];
-        }
-
-      _gdk_quartz_event_loop_release_event (nsevent);
-    }
-}
-
-gboolean
-_gdk_quartz_get_setting (const gchar *name,
-                         GValue      *value)
-{
-  if (strcmp (name, "gtk-double-click-time") == 0)
-    {
-      NSUserDefaults *defaults;
-      float t;
-
-      GDK_QUARTZ_ALLOC_POOL;
-
-      defaults = [NSUserDefaults standardUserDefaults];
-            
-      t = [defaults floatForKey:@"com.apple.mouse.doubleClickThreshold"];
-      if (t == 0.0)
-       {
-         /* No user setting, use the default in OS X. */
-         t = 0.5;
-       }
-
-      GDK_QUARTZ_RELEASE_POOL;
-
-      g_value_set_int (value, t * 1000);
-
-      return TRUE;
-    }
-  else if (strcmp (name, "gtk-font-name") == 0)
-    {
-      NSString *name;
-      char *str;
-      gint size;
-
-      GDK_QUARTZ_ALLOC_POOL;
-
-      name = [[NSFont systemFontOfSize:0] familyName];
-      size = (gint)[[NSFont userFontOfSize:0] pointSize];
-
-      /* Let's try to use the "views" font size (12pt) by default. This is
-       * used for lists/text/other "content" which is the largest parts of
-       * apps, using the "regular control" size (13pt) looks a bit out of
-       * place. We might have to tweak this.
-       */
-
-      /* The size has to be hardcoded as there doesn't seem to be a way to
-       * get the views font size programmatically.
-       */
-      str = g_strdup_printf ("%s %d", [name UTF8String], size);
-      g_value_set_string (value, str);
-      g_free (str);
-
-      GDK_QUARTZ_RELEASE_POOL;
-
-      return TRUE;
-    }
-  else if (strcmp (name, "gtk-primary-button-warps-slider") == 0)
-    {
-      GDK_QUARTZ_ALLOC_POOL;
-
-      BOOL setting = [[NSUserDefaults standardUserDefaults] boolForKey:@"AppleScrollerPagingBehavior"];
-
-      /* If the Apple property is YES, it means "warp" */
-      g_value_set_boolean (value, setting == YES);
-
-      GDK_QUARTZ_RELEASE_POOL;
-
-      return TRUE;
-    }
-  else if (strcmp (name, "gtk-shell-shows-desktop") == 0)
-    {
-      GDK_QUARTZ_ALLOC_POOL;
-
-      g_value_set_boolean (value, TRUE);
-
-      GDK_QUARTZ_RELEASE_POOL;
-
-      return TRUE;
-    }
-  
-  /* FIXME: Add more settings */
-
-  return FALSE;
-}
-
-void
-_gdk_quartz_display_event_data_copy (GdkDisplay     *display,
-                                     const GdkEvent *src,
-                                     GdkEvent       *dst)
-{
-  GdkEventPrivate *priv_src = (GdkEventPrivate *) src;
-  GdkEventPrivate *priv_dst = (GdkEventPrivate *) dst;
-
-  if (priv_src->windowing_data)
-    {
-      priv_dst->windowing_data = priv_src->windowing_data;
-      [(NSEvent *)priv_dst->windowing_data retain];
-    }
-}
-
-void
-_gdk_quartz_display_event_data_free (GdkDisplay *display,
-                                     GdkEvent   *event)
-{
-  GdkEventPrivate *priv = (GdkEventPrivate *) event;
-
-  if (priv->windowing_data)
-    {
-      [(NSEvent *)priv->windowing_data release];
-      priv->windowing_data = NULL;
-    }
-}
diff --git a/gdk/quartz/gdkglcontext-quartz.c b/gdk/quartz/gdkglcontext-quartz.c
deleted file mode 100644 (file)
index cc2e02d..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/* GDK - The GIMP Drawing Kit
- *
- * gdkglcontext-quartz.c: Quartz specific OpenGL wrappers
- *
- * Copyright © 2014  Emmanuele Bassi
- * Copyright © 2014  Alexander Larsson
- * Copyright © 2014  Brion Vibber
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include "gdkglcontext-quartz.h"
-
-#include "gdkintl.h"
-
-GdkGLContext *
-gdk_quartz_surface_create_gl_context (GdkSurface     *window,
-                                     gboolean       attached,
-                                     GdkGLContext  *share,
-                                     GError       **error)
-{
-  /* FIXME: implement */
-  g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
-                       _("Not implemented on OS X"));
-  return NULL;
-}
diff --git a/gdk/quartz/gdkglcontext-quartz.h b/gdk/quartz/gdkglcontext-quartz.h
deleted file mode 100644 (file)
index 080316e..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/* GDK - The GIMP Drawing Kit
- *
- * gdkglcontext-quartz.h: Private Quartz specific OpenGL wrappers
- *
- * Copyright © 2014  Emmanuele Bassi
- * Copyright © 2014  Red Hat, Int
- * Copyright © 2014  Brion Vibber
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_GL_CONTEXT__
-#define __GDK_QUARTZ_GL_CONTEXT__
-
-#include "gdkglcontextprivate.h"
-#include "gdksurface.h"
-#include "gdkinternals.h"
-
-G_BEGIN_DECLS
-
-GdkGLContext *  gdk_quartz_surface_create_gl_context                (GdkSurface         *window,
-                                                                    gboolean           attach,
-                                                                    GdkGLContext      *share,
-                                                                    GError           **error);
-
-G_END_DECLS
-
-#endif /* __GDK_QUARTZ_GL_CONTEXT__ */
diff --git a/gdk/quartz/gdkglobals-quartz.c b/gdk/quartz/gdkglobals-quartz.c
deleted file mode 100644 (file)
index a1cfc2f..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/* gdkglobals-quartz.c
- *
- * Copyright (C) 2005 Imendio AB
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include "gdktypes.h"
-#include "gdkquartz.h"
-#include "gdkscreen-quartz.h"
-
-GdkDisplay *_gdk_display = NULL;
-GdkQuartzScreen *_gdk_screen = NULL;
-GdkSurface *_gdk_root = NULL;
-GdkDeviceManager *_gdk_device_manager = NULL;
-
-GdkOSXVersion
-gdk_quartz_osx_version (void)
-{
-  static gint32 minor = GDK_OSX_UNSUPPORTED;
-
-  if (minor == GDK_OSX_UNSUPPORTED)
-    {
-      OSErr err = Gestalt (gestaltSystemVersionMinor, (SInt32*)&minor);
-
-      g_return_val_if_fail (err == noErr, GDK_OSX_UNSUPPORTED);
-    }
-
-  if (minor < GDK_OSX_MIN)
-    return GDK_OSX_UNSUPPORTED;
-  else if (minor > GDK_OSX_CURRENT)
-    return GDK_OSX_NEW;
-  else
-    return minor;
-}
diff --git a/gdk/quartz/gdkkeys-quartz.c b/gdk/quartz/gdkkeys-quartz.c
deleted file mode 100644 (file)
index baa8614..0000000
+++ /dev/null
@@ -1,850 +0,0 @@
-/* gdkkeys-quartz.c
- *
- * Copyright (C) 2000 Red Hat, Inc.
- * Copyright (C) 2005 Imendio AB
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-/* Some parts of this code come from quartzKeyboard.c,
- * from the Apple X11 Server.
- *
- * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
- *
- *  Permission is hereby granted, free of charge, to any person
- *  obtaining a copy of this software and associated documentation files
- *  (the "Software"), to deal in the Software without restriction,
- *  including without limitation the rights to use, copy, modify, merge,
- *  publish, distribute, sublicense, and/or sell copies of the Software,
- *  and to permit persons to whom the Software is furnished to do so,
- *  subject to the following conditions:
- *
- *  The above copyright notice and this permission notice shall be
- *  included in all copies or substantial portions of the Software.
- *
- *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *  NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
- *  HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- *  DEALINGS IN THE SOFTWARE.
- *
- *  Except as contained in this notice, the name(s) of the above
- *  copyright holders shall not be used in advertising or otherwise to
- *  promote the sale, use or other dealings in this Software without
- *  prior written authorization.
- */
-
-#include "config.h"
-
-#include <Carbon/Carbon.h>
-#include <AppKit/NSEvent.h>
-#include "gdk.h"
-#include "gdkquartzkeys.h"
-#include "gdkkeysprivate.h"
-#include "gdkkeysyms.h"
-
-#define NUM_KEYCODES 128
-#define KEYVALS_PER_KEYCODE 4
-
-static GdkKeymap *default_keymap = NULL;
-
-struct _GdkQuartzKeymap
-{
-  GdkKeymap keymap;
-};
-
-struct _GdkQuartzKeymapClass
-{
-  GdkKeymapClass keymap_class;
-};
-
-G_DEFINE_TYPE (GdkQuartzKeymap, gdk_quartz_keymap, GDK_TYPE_KEYMAP)
-
-GdkKeymap *
-_gdk_quartz_display_get_keymap (GdkDisplay *display)
-{
-  if (default_keymap == NULL)
-    default_keymap = g_object_new (gdk_quartz_keymap_get_type (), NULL);
-
-  return default_keymap;
-}
-
-/* This is a table of all keyvals. Each keycode gets KEYVALS_PER_KEYCODE entries.
- * TThere is 1 keyval per modifier (Nothing, Shift, Alt, Shift+Alt);
- */
-static guint *keyval_array = NULL;
-
-static inline UniChar
-macroman2ucs (unsigned char c)
-{
-  /* Precalculated table mapping MacRoman-128 to Unicode. Generated
-     by creating single element CFStringRefs then extracting the
-     first character. */
-  
-  static const unsigned short table[128] = {
-    0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1,
-    0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
-    0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3,
-    0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
-    0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf,
-    0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8,
-    0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211,
-    0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8,
-    0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab,
-    0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153,
-    0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca,
-    0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
-    0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1,
-    0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
-    0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc,
-    0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7
-  };
-
-  if (c < 128)
-    return c;
-  else
-    return table[c - 128];
-}
-
-const static struct {
-  guint keycode;
-  guint keyval;
-  unsigned int modmask; /* So we can tell when a mod key is pressed/released */
-} modifier_keys[] = {
-  {  54, GDK_KEY_Meta_R,    NSCommandKeyMask },
-  {  55, GDK_KEY_Meta_L,    NSCommandKeyMask },
-  {  56, GDK_KEY_Shift_L,   NSShiftKeyMask },
-  {  57, GDK_KEY_Caps_Lock, NSAlphaShiftKeyMask },
-  {  58, GDK_KEY_Alt_L,     NSAlternateKeyMask },
-  {  59, GDK_KEY_Control_L, NSControlKeyMask },
-  {  60, GDK_KEY_Shift_R,   NSShiftKeyMask },
-  {  61, GDK_KEY_Alt_R,     NSAlternateKeyMask },
-  {  62, GDK_KEY_Control_R, NSControlKeyMask }
-};
-
-const static struct {
-  guint keycode;
-  guint keyval;
-} function_keys[] = {
-  { 122, GDK_KEY_F1 },
-  { 120, GDK_KEY_F2 },
-  {  99, GDK_KEY_F3 },
-  { 118, GDK_KEY_F4 },
-  {  96, GDK_KEY_F5 },
-  {  97, GDK_KEY_F6 },
-  {  98, GDK_KEY_F7 },
-  { 100, GDK_KEY_F8 },
-  { 101, GDK_KEY_F9 },
-  { 109, GDK_KEY_F10 },
-  { 103, GDK_KEY_F11 },
-  { 111, GDK_KEY_F12 },
-  { 105, GDK_KEY_F13 },
-  { 107, GDK_KEY_F14 },
-  { 113, GDK_KEY_F15 },
-  { 106, GDK_KEY_F16 }
-};
-
-const static struct {
-  guint keycode;
-  guint normal_keyval, keypad_keyval;
-} known_numeric_keys[] = {
-  { 65, GDK_KEY_period, GDK_KEY_KP_Decimal },
-  { 67, GDK_KEY_asterisk, GDK_KEY_KP_Multiply },
-  { 69, GDK_KEY_plus, GDK_KEY_KP_Add },
-  { 75, GDK_KEY_slash, GDK_KEY_KP_Divide },
-  { 76, GDK_KEY_Return, GDK_KEY_KP_Enter },
-  { 78, GDK_KEY_minus, GDK_KEY_KP_Subtract },
-  { 81, GDK_KEY_equal, GDK_KEY_KP_Equal },
-  { 82, GDK_KEY_0, GDK_KEY_KP_0 },
-  { 83, GDK_KEY_1, GDK_KEY_KP_1 },
-  { 84, GDK_KEY_2, GDK_KEY_KP_2 },
-  { 85, GDK_KEY_3, GDK_KEY_KP_3 },
-  { 86, GDK_KEY_4, GDK_KEY_KP_4 },
-  { 87, GDK_KEY_5, GDK_KEY_KP_5 },
-  { 88, GDK_KEY_6, GDK_KEY_KP_6 },
-  { 89, GDK_KEY_7, GDK_KEY_KP_7 },
-  { 91, GDK_KEY_8, GDK_KEY_KP_8 },
-  { 92, GDK_KEY_9, GDK_KEY_KP_9 }
-};
-
-/* These values aren't covered by gdk_unicode_to_keyval */
-const static struct {
-  gunichar ucs_value;
-  guint keyval;
-} special_ucs_table [] = {
-  { 0x0001, GDK_KEY_Home },
-  { 0x0003, GDK_KEY_Return },
-  { 0x0004, GDK_KEY_End },
-  { 0x0008, GDK_KEY_BackSpace },
-  { 0x0009, GDK_KEY_Tab },
-  { 0x000b, GDK_KEY_Page_Up },
-  { 0x000c, GDK_KEY_Page_Down },
-  { 0x000d, GDK_KEY_Return },
-  { 0x001b, GDK_KEY_Escape },
-  { 0x001c, GDK_KEY_Left },
-  { 0x001d, GDK_KEY_Right },
-  { 0x001e, GDK_KEY_Up },
-  { 0x001f, GDK_KEY_Down },
-  { 0x007f, GDK_KEY_Delete },
-  { 0xf027, GDK_KEY_dead_acute },
-  { 0xf060, GDK_KEY_dead_grave },
-  { 0xf300, GDK_KEY_dead_grave },
-  { 0xf0b4, GDK_KEY_dead_acute },
-  { 0xf301, GDK_KEY_dead_acute },
-  { 0xf385, GDK_KEY_dead_acute },
-  { 0xf05e, GDK_KEY_dead_circumflex },
-  { 0xf2c6, GDK_KEY_dead_circumflex },
-  { 0xf302, GDK_KEY_dead_circumflex },
-  { 0xf07e, GDK_KEY_dead_tilde },
-  { 0xf2dc, GDK_KEY_dead_tilde },
-  { 0xf303, GDK_KEY_dead_tilde },
-  { 0xf342, GDK_KEY_dead_perispomeni },
-  { 0xf0af, GDK_KEY_dead_macron },
-  { 0xf304, GDK_KEY_dead_macron },
-  { 0xf2d8, GDK_KEY_dead_breve },
-  { 0xf306, GDK_KEY_dead_breve },
-  { 0xf2d9, GDK_KEY_dead_abovedot },
-  { 0xf307, GDK_KEY_dead_abovedot },
-  { 0xf0a8, GDK_KEY_dead_diaeresis },
-  { 0xf308, GDK_KEY_dead_diaeresis },
-  { 0xf2da, GDK_KEY_dead_abovering },
-  { 0xf30A, GDK_KEY_dead_abovering },
-  { 0xf022, GDK_KEY_dead_doubleacute },
-  { 0xf2dd, GDK_KEY_dead_doubleacute },
-  { 0xf30B, GDK_KEY_dead_doubleacute },
-  { 0xf2c7, GDK_KEY_dead_caron },
-  { 0xf30C, GDK_KEY_dead_caron },
-  { 0xf0be, GDK_KEY_dead_cedilla },
-  { 0xf327, GDK_KEY_dead_cedilla },
-  { 0xf2db, GDK_KEY_dead_ogonek },
-  { 0xf328, GDK_KEY_dead_ogonek },
-  { 0xfe5d, GDK_KEY_dead_iota },
-  { 0xf323, GDK_KEY_dead_belowdot },
-  { 0xf309, GDK_KEY_dead_hook },
-  { 0xf31B, GDK_KEY_dead_horn },
-  { 0xf02d, GDK_KEY_dead_stroke },
-  { 0xf335, GDK_KEY_dead_stroke },
-  { 0xf336, GDK_KEY_dead_stroke },
-  { 0xf313, GDK_KEY_dead_abovecomma },
-  /*  { 0xf313, GDK_KEY_dead_psili }, */
-  { 0xf314, GDK_KEY_dead_abovereversedcomma },
-  /*  { 0xf314, GDK_KEY_dead_dasia }, */
-  { 0xf30F, GDK_KEY_dead_doublegrave },
-  { 0xf325, GDK_KEY_dead_belowring },
-  { 0xf2cd, GDK_KEY_dead_belowmacron },
-  { 0xf331, GDK_KEY_dead_belowmacron },
-  { 0xf32D, GDK_KEY_dead_belowcircumflex },
-  { 0xf330, GDK_KEY_dead_belowtilde },
-  { 0xf32E, GDK_KEY_dead_belowbreve },
-  { 0xf324, GDK_KEY_dead_belowdiaeresis },
-  { 0xf311, GDK_KEY_dead_invertedbreve },
-  { 0xf02c, GDK_KEY_dead_belowcomma },
-  { 0xf326, GDK_KEY_dead_belowcomma }
-};
-
-static void
-update_keymap (void)
-{
-  const void *chr_data = NULL;
-  guint *p;
-  int i;
-
-  /* Note: we could check only if building against the 10.5 SDK instead, but
-   * that would make non-xml layouts not work in 32-bit which would be a quite
-   * bad regression. This way, old unsupported layouts will just not work in
-   * 64-bit.
-   */
-#ifdef __LP64__
-  TISInputSourceRef new_layout = TISCopyCurrentKeyboardLayoutInputSource ();
-  CFDataRef layout_data_ref;
-
-#else
-  KeyboardLayoutRef new_layout;
-  KeyboardLayoutKind layout_kind;
-
-  KLGetCurrentKeyboardLayout (&new_layout);
-#endif
-
-  g_free (keyval_array);
-  keyval_array = g_new0 (guint, NUM_KEYCODES * KEYVALS_PER_KEYCODE);
-
-#ifdef __LP64__
-  layout_data_ref = (CFDataRef) TISGetInputSourceProperty
-    (new_layout, kTISPropertyUnicodeKeyLayoutData);
-
-  if (layout_data_ref)
-    chr_data = CFDataGetBytePtr (layout_data_ref);
-
-  if (chr_data == NULL)
-    {
-      g_error ("cannot get keyboard layout data");
-      return;
-    }
-#else
-
-  /* Get the layout kind */
-  KLGetKeyboardLayoutProperty (new_layout, kKLKind, (const void **)&layout_kind);
-
-  /* 8-bit-only keyabord layout */
-  if (layout_kind == kKLKCHRKind)
-    {
-      /* Get chr data */
-      KLGetKeyboardLayoutProperty (new_layout, kKLKCHRData, (const void **)&chr_data);
-
-      for (i = 0; i < NUM_KEYCODES; i++)
-        {
-          int j;
-          UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
-
-          p = keyval_array + i * KEYVALS_PER_KEYCODE;
-
-          for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
-            {
-              UInt32 c, state = 0;
-              UInt16 key_code;
-              UniChar uc;
-
-              key_code = modifiers[j] | i;
-              c = KeyTranslate (chr_data, key_code, &state);
-
-              if (state != 0)
-                {
-                  UInt32 state2 = 0;
-                  c = KeyTranslate (chr_data, key_code | 128, &state2);
-                }
-
-              if (c != 0 && c != 0x10)
-                {
-                  int k;
-                  gboolean found = FALSE;
-
-                  /* FIXME: some keyboard layouts (e.g. Russian) use a
-                   * different 8-bit character set. We should check
-                   * for this. Not a serious problem, because most
-                   * (all?) of these layouts also have a uchr version.
-                   */
-                  uc = macroman2ucs (c);
-
-                  for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
-                    {
-                      if (special_ucs_table[k].ucs_value == uc)
-                        {
-                          p[j] = special_ucs_table[k].keyval;
-                          found = TRUE;
-                          break;
-                        }
-                    }
-
-                  /* Special-case shift-tab since GTK+ expects
-                   * GDK_KEY_ISO_Left_Tab for that.
-                   */
-                  if (found && p[j] == GDK_KEY_Tab && modifiers[j] == shiftKey)
-                    p[j] = GDK_KEY_ISO_Left_Tab;
-
-                  if (!found)
-                    p[j] = gdk_unicode_to_keyval (uc);
-                }
-            }
-
-          if (p[3] == p[2])
-            p[3] = 0;
-          if (p[2] == p[1])
-            p[2] = 0;
-          if (p[1] == p[0])
-            p[1] = 0;
-          if (p[0] == p[2] &&
-              p[1] == p[3])
-            p[2] = p[3] = 0;
-        }
-    }
-  /* unicode keyboard layout */
-  else if (layout_kind == kKLKCHRuchrKind || layout_kind == kKLuchrKind)
-    {
-      /* Get chr data */
-      KLGetKeyboardLayoutProperty (new_layout, kKLuchrData, (const void **)&chr_data);
-#endif
-
-      for (i = 0; i < NUM_KEYCODES; i++)
-        {
-          int j;
-          UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
-          UniChar chars[4];
-          UniCharCount nChars;
-
-          p = keyval_array + i * KEYVALS_PER_KEYCODE;
-
-          for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
-            {
-              UInt32 state = 0;
-              OSStatus err;
-              UInt16 key_code;
-              UniChar uc;
-
-              key_code = modifiers[j] | i;
-              err = UCKeyTranslate (chr_data, i, kUCKeyActionDisplay,
-                                    (modifiers[j] >> 8) & 0xFF,
-                                    LMGetKbdType(),
-                                    0,
-                                    &state, 4, &nChars, chars);
-
-              /* FIXME: Theoretically, we can get multiple UTF-16
-               * values; we should convert them to proper unicode and
-               * figure out whether there are really keyboard layouts
-               * that give us more than one character for one
-               * keypress.
-               */
-              if (err == noErr && nChars == 1)
-                {
-                  int k;
-                  gboolean found = FALSE;
-
-                  /* A few <Shift><Option>keys return two characters,
-                   * the first of which is U+00a0, which isn't
-                   * interesting; so we return the second. More
-                   * sophisticated handling is the job of a
-                   * GtkIMContext.
-                   *
-                   * If state isn't zero, it means that it's a dead
-                   * key of some sort. Some of those are enumerated in
-                   * the special_ucs_table with the high nibble set to
-                   * f to push it into the private use range. Here we
-                   * do the same.
-                   */
-                  if (state != 0)
-                    chars[nChars - 1] |= 0xf000;
-                  uc = chars[nChars - 1];
-
-                  for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
-                    {
-                      if (special_ucs_table[k].ucs_value == uc)
-                        {
-                          p[j] = special_ucs_table[k].keyval;
-                          found = TRUE;
-                          break;
-                        }
-                    }
-
-                  /* Special-case shift-tab since GTK+ expects
-                   * GDK_KEY_ISO_Left_Tab for that.
-                   */
-                  if (found && p[j] == GDK_KEY_Tab && modifiers[j] == shiftKey)
-                    p[j] = GDK_KEY_ISO_Left_Tab;
-
-                  if (!found)
-                    p[j] = gdk_unicode_to_keyval (uc);
-                }
-            }
-
-          if (p[3] == p[2])
-            p[3] = 0;
-          if (p[2] == p[1])
-            p[2] = 0;
-          if (p[1] == p[0])
-            p[1] = 0;
-          if (p[0] == p[2] &&
-              p[1] == p[3])
-            p[2] = p[3] = 0;
-        }
-#ifndef __LP64__
-    }
-  else
-    {
-      g_error ("unknown type of keyboard layout (neither KCHR nor uchr)"
-               " - not supported right now");
-    }
-#endif
-
-  for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
-    {
-      p = keyval_array + modifier_keys[i].keycode * KEYVALS_PER_KEYCODE;
-
-      if (p[0] == 0 && p[1] == 0 &&
-          p[2] == 0 && p[3] == 0)
-        p[0] = modifier_keys[i].keyval;
-    }
-
-  for (i = 0; i < G_N_ELEMENTS (function_keys); i++)
-    {
-      p = keyval_array + function_keys[i].keycode * KEYVALS_PER_KEYCODE;
-
-      p[0] = function_keys[i].keyval;
-      p[1] = p[2] = p[3] = 0;
-    }
-
-  for (i = 0; i < G_N_ELEMENTS (known_numeric_keys); i++)
-    {
-      p = keyval_array + known_numeric_keys[i].keycode * KEYVALS_PER_KEYCODE;
-
-      if (p[0] == known_numeric_keys[i].normal_keyval)
-        p[0] = known_numeric_keys[i].keypad_keyval;
-    }
-
-  if (default_keymap != NULL)
-    g_signal_emit_by_name (default_keymap, "keys-changed");
-}
-
-static PangoDirection
-gdk_quartz_keymap_get_direction (GdkKeymap *keymap)
-{
-  return PANGO_DIRECTION_NEUTRAL;
-}
-
-static gboolean
-gdk_quartz_keymap_have_bidi_layouts (GdkKeymap *keymap)
-{
-  /* FIXME: Can we implement this? */
-  return FALSE;
-}
-
-static gboolean
-gdk_quartz_keymap_get_caps_lock_state (GdkKeymap *keymap)
-{
-  /* FIXME: Implement this. */
-  return FALSE;
-}
-
-static gboolean
-gdk_quartz_keymap_get_num_lock_state (GdkKeymap *keymap)
-{
-  /* FIXME: Implement this. */
-  return FALSE;
-}
-
-static gboolean
-gdk_quartz_keymap_get_scroll_lock_state (GdkKeymap *keymap)
-{
-  /* FIXME: Implement this. */
-  return FALSE;
-}
-
-static gboolean
-gdk_quartz_keymap_get_entries_for_keyval (GdkKeymap     *keymap,
-                                          guint          keyval,
-                                          GdkKeymapKey **keys,
-                                          gint          *n_keys)
-{
-  GArray *keys_array;
-  int i;
-
-  *n_keys = 0;
-  keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
-
-  for (i = 0; i < NUM_KEYCODES * KEYVALS_PER_KEYCODE; i++)
-    {
-      GdkKeymapKey key;
-
-      if (keyval_array[i] != keyval)
-       continue;
-
-      (*n_keys)++;
-
-      key.keycode = i / KEYVALS_PER_KEYCODE;
-      key.group = (i % KEYVALS_PER_KEYCODE) >= 2;
-      key.level = i % 2;
-
-      g_array_append_val (keys_array, key);
-    }
-
-  *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
-  
-  return *n_keys > 0;;
-}
-
-static gboolean
-gdk_quartz_keymap_get_entries_for_keycode (GdkKeymap     *keymap,
-                                           guint          hardware_keycode,
-                                           GdkKeymapKey **keys,
-                                           guint        **keyvals,
-                                           gint          *n_entries)
-{
-  GArray *keys_array, *keyvals_array;
-  int i;
-  guint *p;
-
-  *n_entries = 0;
-
-  if (hardware_keycode > NUM_KEYCODES)
-    return FALSE;
-
-  if (keys)
-    keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
-  else
-    keys_array = NULL;
-
-  if (keyvals)
-    keyvals_array = g_array_new (FALSE, FALSE, sizeof (guint));
-  else
-    keyvals_array = NULL;
-
-  p = keyval_array + hardware_keycode * KEYVALS_PER_KEYCODE;
-  
-  for (i = 0; i < KEYVALS_PER_KEYCODE; i++)
-    {
-      if (!p[i])
-       continue;
-
-      (*n_entries)++;
-      
-      if (keyvals_array)
-       g_array_append_val (keyvals_array, p[i]);
-
-      if (keys_array)
-       {
-         GdkKeymapKey key;
-
-         key.keycode = hardware_keycode;
-         key.group = i >= 2;
-         key.level = i % 2;
-
-         g_array_append_val (keys_array, key);
-       }
-    }
-  
-  if (keys)
-    *keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
-
-  if (keyvals)
-    *keyvals = (guint *)g_array_free (keyvals_array, FALSE);
-
-  return *n_entries > 0;
-}
-
-#define GET_KEYVAL(keycode, group, level) (keyval_array[(keycode * KEYVALS_PER_KEYCODE + group * 2 + level)])
-
-static guint
-gdk_quartz_keymap_lookup_key (GdkKeymap          *keymap,
-                              const GdkKeymapKey *key)
-{
-  return GET_KEYVAL (key->keycode, key->group, key->level);
-}
-
-static guint
-translate_keysym (guint           hardware_keycode,
-                 gint            group,
-                 GdkModifierType state,
-                 gint           *effective_group,
-                 gint           *effective_level)
-{
-  gint level;
-  guint tmp_keyval;
-
-  level = (state & GDK_SHIFT_MASK) ? 1 : 0;
-
-  if (!(GET_KEYVAL (hardware_keycode, group, 0) || GET_KEYVAL (hardware_keycode, group, 1)) &&
-      (GET_KEYVAL (hardware_keycode, 0, 0) || GET_KEYVAL (hardware_keycode, 0, 1)))
-    group = 0;
-
-  if (!GET_KEYVAL (hardware_keycode, group, level) &&
-      GET_KEYVAL (hardware_keycode, group, 0))
-    level = 0;
-
-  tmp_keyval = GET_KEYVAL (hardware_keycode, group, level);
-
-  if (state & GDK_LOCK_MASK)
-    {
-      guint upper = gdk_keyval_to_upper (tmp_keyval);
-      if (upper != tmp_keyval)
-        tmp_keyval = upper;
-    }
-
-  if (effective_group)
-    *effective_group = group;
-  if (effective_level)
-    *effective_level = level;
-
-  return tmp_keyval;
-}
-
-static gboolean
-gdk_quartz_keymap_translate_keyboard_state (GdkKeymap       *keymap,
-                                            guint            hardware_keycode,
-                                            GdkModifierType  state,
-                                            gint             group,
-                                            guint           *keyval,
-                                            gint            *effective_group,
-                                            gint            *level,
-                                            GdkModifierType *consumed_modifiers)
-{
-  guint tmp_keyval;
-  GdkModifierType bit;
-
-  if (keyval)
-    *keyval = 0;
-  if (effective_group)
-    *effective_group = 0;
-  if (level)
-    *level = 0;
-  if (consumed_modifiers)
-    *consumed_modifiers = 0;
-
-  if (hardware_keycode < 0 || hardware_keycode >= NUM_KEYCODES)
-    return FALSE;
-
-  tmp_keyval = translate_keysym (hardware_keycode, group, state, level, effective_group);
-
-  /* Check if modifiers modify the keyval */
-  if (consumed_modifiers)
-    {
-      guint tmp_modifiers = (state & GDK_MODIFIER_MASK);
-
-      for (bit = 1; bit <= tmp_modifiers; bit <<= 1)
-        {
-          if ((bit & tmp_modifiers) &&
-              translate_keysym (hardware_keycode, group, state & ~bit,
-                                NULL, NULL) == tmp_keyval)
-            tmp_modifiers &= ~bit;
-        }
-
-      *consumed_modifiers = tmp_modifiers;
-    }
-
-  if (keyval)
-    *keyval = tmp_keyval; 
-
-  return TRUE;
-}
-
-static void
-gdk_quartz_keymap_add_virtual_modifiers (GdkKeymap       *keymap,
-                                         GdkModifierType *state)
-{
-  if (*state & GDK_MOD2_MASK)
-    *state |= GDK_META_MASK;
-}
-
-static gboolean
-gdk_quartz_keymap_map_virtual_modifiers (GdkKeymap       *keymap,
-                                         GdkModifierType *state)
-{
-  if (*state & GDK_META_MASK)
-    *state |= GDK_MOD2_MASK;
-
-  return TRUE;
-}
-
-/* What sort of key event is this? Returns one of
- * GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_NOTHING (should be ignored)
- */
-GdkEventType
-_gdk_quartz_keys_event_type (NSEvent *event)
-{
-  unsigned short keycode;
-  unsigned int flags;
-  int i;
-  
-  switch ([event type])
-    {
-    case NSKeyDown:
-      return GDK_KEY_PRESS;
-    case NSKeyUp:
-      return GDK_KEY_RELEASE;
-    case NSFlagsChanged:
-      break;
-    default:
-      g_assert_not_reached ();
-    }
-  
-  /* For flags-changed events, we have to find the special key that caused the
-   * event, and see if it's in the modifier mask. */
-  keycode = [event keyCode];
-  flags = [event modifierFlags];
-  
-  for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
-    {
-      if (modifier_keys[i].keycode == keycode)
-       {
-         if (flags & modifier_keys[i].modmask)
-           return GDK_KEY_PRESS;
-         else
-           return GDK_KEY_RELEASE;
-       }
-    }
-  
-  /* Some keypresses (eg: Expose' activations) seem to trigger flags-changed
-   * events for no good reason. Ignore them! */
-  return GDK_NOTHING;
-}
-
-gboolean
-_gdk_quartz_keys_is_modifier (guint keycode)
-{
-  gint i;
-  
-  for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
-    {
-      if (modifier_keys[i].modmask == 0)
-       break;
-
-      if (modifier_keys[i].keycode == keycode)
-       return TRUE;
-    }
-
-  return FALSE;
-}
-
-static void
-input_sources_changed_notification (CFNotificationCenterRef  center,
-                                    void                    *observer,
-                                    CFStringRef              name,
-                                    const void              *object,
-                                    CFDictionaryRef          userInfo)
-{
-  update_keymap ();
-}
-
-static void
-gdk_quartz_keymap_init (GdkQuartzKeymap *keymap)
-{
-  update_keymap ();
-  CFNotificationCenterAddObserver (CFNotificationCenterGetDistributedCenter (),
-                                   keymap,
-                                   input_sources_changed_notification,
-                                   CFSTR ("AppleSelectedInputSourcesChangedNotification"),
-                                   NULL,
-                                   CFNotificationSuspensionBehaviorDeliverImmediately);
-}
-
-static void
-gdk_quartz_keymap_finalize (GObject *object)
-{
-  CFNotificationCenterRemoveObserver (CFNotificationCenterGetDistributedCenter (),
-                                      object,
-                                      CFSTR ("AppleSelectedInputSourcesChangedNotification"),
-                                      NULL);
-
-  G_OBJECT_CLASS (gdk_quartz_keymap_parent_class)->finalize (object);
-}
-
-static void
-gdk_quartz_keymap_class_init (GdkQuartzKeymapClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
-
-  object_class->finalize = gdk_quartz_keymap_finalize;
-
-  keymap_class->get_direction = gdk_quartz_keymap_get_direction;
-  keymap_class->have_bidi_layouts = gdk_quartz_keymap_have_bidi_layouts;
-  keymap_class->get_caps_lock_state = gdk_quartz_keymap_get_caps_lock_state;
-  keymap_class->get_num_lock_state = gdk_quartz_keymap_get_num_lock_state;
-  keymap_class->get_scroll_lock_state = gdk_quartz_keymap_get_scroll_lock_state;
-  keymap_class->get_entries_for_keyval = gdk_quartz_keymap_get_entries_for_keyval;
-  keymap_class->get_entries_for_keycode = gdk_quartz_keymap_get_entries_for_keycode;
-  keymap_class->lookup_key = gdk_quartz_keymap_lookup_key;
-  keymap_class->translate_keyboard_state = gdk_quartz_keymap_translate_keyboard_state;
-  keymap_class->add_virtual_modifiers = gdk_quartz_keymap_add_virtual_modifiers;
-  keymap_class->map_virtual_modifiers = gdk_quartz_keymap_map_virtual_modifiers;
-}
diff --git a/gdk/quartz/gdkmonitor-quartz.c b/gdk/quartz/gdkmonitor-quartz.c
deleted file mode 100644 (file)
index b3e11f7..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright © 2017 Tom Schoonjans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include <glib.h>
-#include <gio/gio.h>
-
-#include "gdkmonitor-quartz.h"
-#include "gdkscreen-quartz.h"
-
-
-G_DEFINE_TYPE (GdkQuartzMonitor, gdk_quartz_monitor, GDK_TYPE_MONITOR)
-
-static void
-gdk_quartz_monitor_get_workarea (GdkMonitor   *monitor,
-                                 GdkRectangle *dest)
-{
-  GdkQuartzScreen *quartz_screen = GDK_QUARTZ_SCREEN(_gdk_screen);
-  GdkQuartzMonitor *quartz_monitor = GDK_QUARTZ_MONITOR(monitor);
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  NSArray *array = [NSScreen screens];
-  if (quartz_monitor->monitor_num < [array count])
-    {
-      NSScreen *screen = [array objectAtIndex:quartz_monitor->monitor_num];
-      NSRect rect = [screen visibleFrame];
-
-      dest->x = rect.origin.x - quartz_screen->min_x;
-      dest->y = quartz_screen->height - (rect.origin.y + rect.size.height) + quartz_screen->min_y;
-      dest->width = rect.size.width;
-      dest->height = rect.size.height;
-    }
-  else
-    *dest = monitor->geometry;
-
-  GDK_QUARTZ_RELEASE_POOL;
-}
-
-static void
-gdk_quartz_monitor_init (GdkQuartzMonitor *monitor)
-{
-}
-
-static void
-gdk_quartz_monitor_class_init (GdkQuartzMonitorClass *class)
-{
-  GDK_MONITOR_CLASS (class)->get_workarea = gdk_quartz_monitor_get_workarea;
-}
-
diff --git a/gdk/quartz/gdkmonitor-quartz.h b/gdk/quartz/gdkmonitor-quartz.h
deleted file mode 100644 (file)
index 468a1d8..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright © 2017 Tom Schoonjans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_MONITOR_PRIVATE_H__
-#define __GDK_QUARTZ_MONITOR_PRIVATE_H__
-
-#include <glib.h>
-#include <gio/gio.h>
-
-#include "gdkmonitorprivate.h"
-
-#include "gdkquartzmonitor.h"
-#include "gdkprivate-quartz.h"
-
-struct _GdkQuartzMonitor
-{
-  GdkMonitor parent;
-
-  gint monitor_num;
-};
-
-struct _GdkQuartzMonitorClass {
-  GdkMonitorClass parent_class;
-};
-
-#endif
-
diff --git a/gdk/quartz/gdkprivate-quartz.h b/gdk/quartz/gdkprivate-quartz.h
deleted file mode 100644 (file)
index 08c86fd..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/* gdksurface-quartz.c
- *
- * Copyright (C) 2005-2007 Imendio AB
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_PRIVATE_QUARTZ_H__
-#define __GDK_PRIVATE_QUARTZ_H__
-
-#define GDK_QUARTZ_ALLOC_POOL NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]
-#define GDK_QUARTZ_RELEASE_POOL [pool release]
-
-#include <gdk/quartz/gdkquartz.h>
-#include <gdk/quartz/gdkdevicemanager-core-quartz.h>
-#include <gdk/quartz/gdkdnd-quartz.h>
-#include <gdk/quartz/gdkscreen-quartz.h>
-#include <gdk/quartz/gdksurface-quartz.h>
-
-#include <gdk/gdk.h>
-
-#include "gdkinternals.h"
-
-#include "config.h"
-
-extern GdkDisplay *_gdk_display;
-extern GdkQuartzScreen *_gdk_screen;
-extern GdkSurface *_gdk_root;
-extern GdkDeviceManager *_gdk_device_manager;
-
-extern GdkDragContext *_gdk_quartz_drag_source_context;
-
-#define GDK_SURFACE_IS_QUARTZ(win)        (GDK_IS_SURFACE_IMPL_QUARTZ (((GdkSurface *)win)->impl))
-
-/* Initialization */
-void _gdk_quartz_surface_init_windowing      (GdkDisplay *display);
-void _gdk_quartz_events_init                (void);
-void _gdk_quartz_event_loop_init            (void);
-
-/* Cursor */
-NSCursor   *_gdk_quartz_cursor_get_ns_cursor        (GdkCursor *cursor);
-
-/* Events */
-typedef enum {
-  GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP
-} GdkQuartzEventSubType;
-
-void         _gdk_quartz_events_update_focus_window    (GdkSurface *new_window,
-                                                        gboolean   got_focus);
-void         _gdk_quartz_events_send_map_event         (GdkSurface *window);
-
-GdkModifierType _gdk_quartz_events_get_current_keyboard_modifiers (void);
-GdkModifierType _gdk_quartz_events_get_current_mouse_modifiers    (void);
-
-void         _gdk_quartz_events_break_all_grabs         (guint32    time);
-
-/* Event loop */
-gboolean   _gdk_quartz_event_loop_check_pending (void);
-NSEvent *  _gdk_quartz_event_loop_get_pending   (void);
-void       _gdk_quartz_event_loop_release_event (NSEvent *event);
-
-/* Keys */
-GdkEventType _gdk_quartz_keys_event_type  (NSEvent   *event);
-gboolean     _gdk_quartz_keys_is_modifier (guint      keycode);
-void         _gdk_quartz_synthesize_null_key_event (GdkSurface *window);
-
-/* Drag and Drop */
-GdkDragContext * _gdk_quartz_surface_drag_begin   (GdkSurface   *window,
-                                                   GdkDevice   *device,
-                                                   GList       *targets,
-                                                   gint         x_root,
-                                                   gint         y_root);
-
-/* Display */
-
-GdkDisplay *    _gdk_quartz_display_open (const gchar *name);
-
-
-/* Screen */
-GdkQuartzScreen  *_gdk_quartz_screen_new                      (void);
-void        _gdk_quartz_screen_update_window_sizes      (GdkQuartzScreen *screen);
-
-/* Screen methods - events */
-gboolean    _gdk_quartz_get_setting                 (const gchar *name,
-                                                     GValue      *value);
-
-
-/* Window */
-gboolean    _gdk_quartz_surface_is_ancestor         (GdkSurface *ancestor,
-                                                     GdkSurface *window);
-void       _gdk_quartz_surface_gdk_xy_to_xy         (gint       gdk_x,
-                                                     gint       gdk_y,
-                                                     gint      *ns_x,
-                                                     gint      *ns_y);
-void       _gdk_quartz_surface_xy_to_gdk_xy         (gint       ns_x,
-                                                     gint       ns_y,
-                                                     gint      *gdk_x,
-                                                     gint      *gdk_y);
-void       _gdk_quartz_surface_nspoint_to_gdk_xy    (NSPoint    point,
-                                                     gint      *x,
-                                                     gint      *y);
-GdkSurface *_gdk_quartz_surface_find_child          (GdkSurface *window,
-                                                     gint       x,
-                                                     gint       y,
-                                                     gboolean   get_toplevel);
-void       _gdk_quartz_surface_attach_to_parent     (GdkSurface *window);
-void       _gdk_quartz_surface_detach_from_parent   (GdkSurface *window);
-void       _gdk_quartz_surface_did_become_main      (GdkSurface *window);
-void       _gdk_quartz_surface_did_resign_main      (GdkSurface *window);
-void       _gdk_quartz_surface_debug_highlight      (GdkSurface *window,
-                                                     gint       number);
-
-void       _gdk_quartz_surface_update_position           (GdkSurface    *window);
-void       _gdk_quartz_surface_update_fullscreen_state   (GdkSurface    *window);
-
-/* Window methods - property */
-gboolean _gdk_quartz_surface_get_property     (GdkSurface    *window,
-                                               GdkAtom       property,
-                                               GdkAtom       type,
-                                               gulong        offset,
-                                               gulong        length,
-                                               gint          pdelete,
-                                               GdkAtom      *actual_property_type,
-                                               gint         *actual_format_type,
-                                               gint         *actual_length,
-                                               guchar      **data);
-void     _gdk_quartz_surface_change_property  (GdkSurface    *window,
-                                               GdkAtom       property,
-                                               GdkAtom       type,
-                                               gint          format,
-                                               GdkPropMode   mode,
-                                               const guchar *data,
-                                               gint          nelements);
-void     _gdk_quartz_surface_delete_property  (GdkSurface    *window,
-                                               GdkAtom       property);
-
-
-#endif /* __GDK_PRIVATE_QUARTZ_H__ */
diff --git a/gdk/quartz/gdkquartz.h b/gdk/quartz/gdkquartz.h
deleted file mode 100644 (file)
index 46e4c85..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-
-/* gdkquartz.h
- *
- * Copyright (C) 2005-2007 Imendio AB
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_H__
-#define __GDK_QUARTZ_H__
-
-#include <AppKit/AppKit.h>
-
-#include <gdk/gdk.h>
-
-G_BEGIN_DECLS
-
-/* NSInteger only exists in Leopard and newer.  This check has to be
- * done after inclusion of the system headers.  If NSInteger has not
- * been defined, we know for sure that we are on 32-bit.
- */
-#ifndef NSINTEGER_DEFINED
-typedef int NSInteger;
-typedef unsigned int NSUInteger;
-#endif
-
-#ifndef CGFLOAT_DEFINED
-typedef float CGFloat;
-#endif
-
-typedef enum
-{
-  GDK_OSX_UNSUPPORTED = 0,
-  GDK_OSX_MIN = 4,
-  GDK_OSX_TIGER = 4,
-  GDK_OSX_LEOPARD = 5,
-  GDK_OSX_SNOW_LEOPARD = 6,
-  GDK_OSX_LION = 7,
-  GDK_OSX_MOUNTAIN_LION = 8,
-  GDK_OSX_MAVERICKS = 9,
-  GDK_OSX_YOSEMITE = 10,
-  GDK_OSX_EL_CAPITAN = 11,
-  GDK_OSX_SIERRA = 12,
-  GDK_OSX_HIGH_SIERRA = 13,
-  GDK_OSX_MOJAVE = 14,
-  GDK_OSX_CURRENT = 14,
-  GDK_OSX_NEW = 99
-} GdkOSXVersion;
-
-GDK_AVAILABLE_IN_ALL
-GdkOSXVersion gdk_quartz_osx_version (void);
-
-GDK_AVAILABLE_IN_ALL
-GdkAtom   gdk_quartz_pasteboard_type_to_atom_libgtk_only        (NSString       *type);
-GDK_AVAILABLE_IN_ALL
-NSString *gdk_quartz_target_to_pasteboard_type_libgtk_only      (const gchar    *target);
-GDK_AVAILABLE_IN_ALL
-NSString *gdk_quartz_atom_to_pasteboard_type_libgtk_only        (GdkAtom         atom);
-
-G_END_DECLS
-
-#define __GDKQUARTZ_H_INSIDE__
-
-#include <gdk/quartz/gdkquartzcursor.h>
-#include <gdk/quartz/gdkquartzdevice-core.h>
-#include <gdk/quartz/gdkquartzdevicemanager-core.h>
-#include <gdk/quartz/gdkquartzdisplay.h>
-#include <gdk/quartz/gdkquartzdisplaymanager.h>
-#include <gdk/quartz/gdkquartzdnd.h>
-#include <gdk/quartz/gdkquartzkeys.h>
-#include <gdk/quartz/gdkquartzmonitor.h>
-#include <gdk/quartz/gdkquartzscreen.h>
-#include <gdk/quartz/gdkquartzutils.h>
-#include <gdk/quartz/gdkquartzsurface.h>
-
-#undef __GDKQUARTZ_H_INSIDE__
-
-#endif /* __GDK_QUARTZ_H__ */
diff --git a/gdk/quartz/gdkquartzcursor.h b/gdk/quartz/gdkquartzcursor.h
deleted file mode 100644 (file)
index d8668b8..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/* gdkquartzcursor.h
- *
- * Copyright (C) 2005-2007  Imendio AB
- * Copyright (C) 2010 Kristian Rietveld  <kris@gtk.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_CURSOR_H__
-#define __GDK_QUARTZ_CURSOR_H__
-
-#if !defined(__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
-#endif
-
-#include <gdk/gdk.h>
-
-G_BEGIN_DECLS
-
-#define GDK_TYPE_QUARTZ_CURSOR              (gdk_quartz_cursor_get_type ())
-#define GDK_QUARTZ_CURSOR(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_QUARTZ_CURSOR, GdkQuartzCursor))
-#define GDK_QUARTZ_CURSOR_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_QUARTZ_CURSOR, GdkQuartzCursorClass))
-#define GDK_IS_QUARTZ_CURSOR(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_QUARTZ_CURSOR))
-#define GDK_IS_QUARTZ_CURSOR_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_QUARTZ_CURSOR))
-#define GDK_QUARTZ_CURSOR_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_QUARTZ_CURSOR, GdkQuartzCursorClass))
-
-#ifdef GTK_COMPILATION
-typedef struct _GdkQuartzCursor GdkQuartzCursor;
-#else
-typedef GdkCursor GdkQuartzCursor;
-#endif
-typedef struct _GdkQuartzCursorClass GdkQuartzCursorClass;
-
-GDK_AVAILABLE_IN_ALL
-GType gdk_quartz_cursor_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GDK_QUARTZ_CURSOR_H__ */
diff --git a/gdk/quartz/gdkquartzdevice-core.h b/gdk/quartz/gdkquartzdevice-core.h
deleted file mode 100644 (file)
index 4b88a0b..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/* GDK - The GIMP Drawing Kit
- * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_DEVICE_CORE_H__
-#define __GDK_QUARTZ_DEVICE_CORE_H__
-
-#if !defined(__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
-#endif
-
-#include <gdk/gdk.h>
-
-G_BEGIN_DECLS
-
-#define GDK_TYPE_QUARTZ_DEVICE_CORE         (gdk_quartz_device_core_get_type ())
-#define GDK_QUARTZ_DEVICE_CORE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_QUARTZ_DEVICE_CORE, GdkQuartzDeviceCore))
-#define GDK_QUARTZ_DEVICE_CORE_CLASS(c)     (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_QUARTZ_DEVICE_CORE, GdkQuartzDeviceCoreClass))
-#define GDK_IS_QUARTZ_DEVICE_CORE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_QUARTZ_DEVICE_CORE))
-#define GDK_IS_QUARTZ_DEVICE_CORE_CLASS(c)  (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_QUARTZ_DEVICE_CORE))
-#define GDK_QUARTZ_DEVICE_CORE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_QUARTZ_DEVICE_CORE, GdkQuartzDeviceCoreClass))
-
-typedef struct _GdkQuartzDeviceCore GdkQuartzDeviceCore;
-typedef struct _GdkQuartzDeviceCoreClass GdkQuartzDeviceCoreClass;
-
-GDK_AVAILABLE_IN_ALL
-GType gdk_quartz_device_core_get_type (void) G_GNUC_CONST;
-
-G_END_DECLS
-
-#endif /* __GDK_QUARTZ_DEVICE_CORE_H__ */
diff --git a/gdk/quartz/gdkquartzdevicemanager-core.h b/gdk/quartz/gdkquartzdevicemanager-core.h
deleted file mode 100644 (file)
index 308152c..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/* GDK - The GIMP Drawing Kit
- * Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_DEVICE_MANAGER_CORE_H__
-#define __GDK_QUARTZ_DEVICE_MANAGER_CORE_H__
-
-#if !defined(__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
-#endif
-
-#include <gdk/gdk.h>
-
-G_BEGIN_DECLS
-
-#define GDK_TYPE_QUARTZ_DEVICE_MANAGER_CORE         (gdk_quartz_device_manager_core_get_type ())
-#define GDK_QUARTZ_DEVICE_MANAGER_CORE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_QUARTZ_DEVICE_MANAGER_CORE, GdkQuartzDeviceManagerCore))
-#define GDK_QUARTZ_DEVICE_MANAGER_CORE_CLASS(c)     (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_QUARTZ_DEVICE_MANAGER_CORE, GdkQuartzDeviceManagerCoreClass))
-#define GDK_IS_QUARTZ_DEVICE_MANAGER_CORE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_QUARTZ_DEVICE_MANAGER_CORE))
-#define GDK_IS_QUARTZ_DEVICE_MANAGER_CORE_CLASS(c)  (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_QUARTZ_DEVICE_MANAGER_CORE))
-#define GDK_QUARTZ_DEVICE_MANAGER_CORE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_QUARTZ_DEVICE_MANAGER_CORE, GdkQuartzDeviceManagerCoreClass))
-
-typedef struct _GdkQuartzDeviceManagerCore GdkQuartzDeviceManagerCore;
-typedef struct _GdkQuartzDeviceManagerCoreClass GdkQuartzDeviceManagerCoreClass;
-
-
-GDK_AVAILABLE_IN_ALL
-GType gdk_quartz_device_manager_core_get_type (void) G_GNUC_CONST;
-
-
-G_END_DECLS
-
-#endif /* __GDK_QUARTZ_DEVICE_MANAGER_CORE_H__ */
diff --git a/gdk/quartz/gdkquartzdisplay.h b/gdk/quartz/gdkquartzdisplay.h
deleted file mode 100644 (file)
index 23ed898..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/* gdkquartzdisplay.h
- *
- * Copyright (C) 2005-2007  Imendio AB
- * Copyright (C) 2010 Kristian Rietveld  <kris@gtk.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_DISPLAY_H__
-#define __GDK_QUARTZ_DISPLAY_H__
-
-#if !defined(__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
-#endif
-
-#include <gdk/gdk.h>
-
-G_BEGIN_DECLS
-
-#define GDK_TYPE_QUARTZ_DISPLAY              (gdk_quartz_display_get_type ())
-#define GDK_QUARTZ_DISPLAY(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_QUARTZ_DISPLAY, GdkQuartzDisplay))
-#define GDK_QUARTZ_DISPLAY_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_QUARTZ_DISPLAY, GdkQuartzDisplayClass))
-#define GDK_IS_QUARTZ_DISPLAY(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_QUARTZ_DISPLAY))
-#define GDK_IS_QUARTZ_DISPLAY_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_QUARTZ_DISPLAY))
-#define GDK_QUARTZ_DISPLAY_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_QUARTZ_DISPLAY, GdkQuartzDisplayClass))
-
-#ifdef GTK_COMPILATION
-typedef struct _GdkQuartzDisplay GdkQuartzDisplay;
-#else
-typedef GdkDisplay GdkQuartzDisplay;
-#endif
-typedef struct _GdkQuartzDisplayClass GdkQuartzDisplayClass;
-
-
-GDK_AVAILABLE_IN_ALL
-GType gdk_quartz_display_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GDK_QUARTZ_DISPLAY_H__ */
diff --git a/gdk/quartz/gdkquartzdisplaymanager.h b/gdk/quartz/gdkquartzdisplaymanager.h
deleted file mode 100644 (file)
index 8aa1938..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/* gdkquartzdisplaymanager.h
- *
- * Copyright (C) 2005-2007  Imendio AB
- * Copyright 2010 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_DISPLAY_MANAGER_H__
-#define __GDK_QUARTZ_DISPLAY_MANAGER_H__
-
-#if !defined(__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
-#endif
-
-#include <gdk/gdk.h>
-
-G_BEGIN_DECLS
-
-#define GDK_TYPE_QUARTZ_DISPLAY_MANAGER    (gdk_quartz_display_manager_get_type ())
-#define GDK_QUARTZ_DISPLAY_MANAGER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_QUARTZ_DISPLAY_MANAGER, GdkQuartzDisplayManager))
-
-#ifdef GTK_COMPILATION
-typedef struct _GdkQuartzDisplayManager GdkQuartzDisplayManager;
-#else
-typedef GdkDisplayManager _GdkQuartzDisplayManager;
-#endif
-typedef struct _GdkDisplayManagerClass GdkQuartzDisplayManagerClass;
-
-
-GDK_AVAILABLE_IN_ALL
-GType gdk_quartz_display_manager_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GDK_QUARTZ_DISPLAY_MANAGER_H__ */
diff --git a/gdk/quartz/gdkquartzdnd.h b/gdk/quartz/gdkquartzdnd.h
deleted file mode 100644 (file)
index 18f3727..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* gdkquartzdnd.h
- *
- * Copyright (C) 2010 Kristian Rietveld  <kris@gtk.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_DND_H__
-#define __GDK_QUARTZ_DND_H__
-
-#if !defined(__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
-#endif
-
-#include <gdk/gdk.h>
-
-G_BEGIN_DECLS
-
-#define GDK_TYPE_QUARTZ_DRAG_CONTEXT              (gdk_quartz_drag_context_get_type ())
-#define GDK_QUARTZ_DRAG_CONTEXT(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_QUARTZ_DRAG_CONTEXT, GdkQuartzDragContext))
-#define GDK_QUARTZ_DRAG_CONTEXT_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_QUARTZ_DRAG_CONTEXT, GdkQuartzDragContextClass))
-#define GDK_IS_QUARTZ_DRAG_CONTEXT(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_QUARTZ_DRAG_CONTEXT))
-#define GDK_IS_QUARTZ_DRAG_CONTEXT_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_QUARTZ_DRAG_CONTEXT))
-#define GDK_QUARTZ_DRAG_CONTEXT_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_QUARTZ_DRAG_CONTEXT, GdkQuartzDragContextClass))
-
-#ifdef GTK_COMPILATION
-typedef struct _GdkQuartzDragContext GdkQuartzDragContext;
-#else
-typedef GdkDragContext GdkQuartzDragContext;
-#endif
-typedef struct _GdkQuartzDragContextClass GdkQuartzDragContextClass;
-
-
-GDK_AVAILABLE_IN_ALL
-GType     gdk_quartz_drag_context_get_type (void);
-
-GDK_AVAILABLE_IN_ALL
-id        gdk_quartz_drag_context_get_dragging_info_libgtk_only (GdkDragContext *context);
-
-GDK_AVAILABLE_IN_ALL
-GdkDragContext *gdk_quartz_drag_source_context_libgtk_only (void);
-
-G_END_DECLS
-
-#endif /* __GDK_QUARTZ_DRAG_CONTEXT_H__ */
diff --git a/gdk/quartz/gdkquartzkeys.h b/gdk/quartz/gdkquartzkeys.h
deleted file mode 100644 (file)
index 9325b95..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/* gdkquartzkeyd.h
- *
- * Copyright (C) 2005  Imendio AB
- * Copyright (C) 2010  Kristian Rietveld  <kris@gtk.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_KEYS_H__
-#define __GDK_QUARTZ_KEYS_H__
-
-#if !defined (__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
-#endif
-
-#include <gdk/gdk.h>
-
-G_BEGIN_DECLS
-
-#define GDK_TYPE_QUARTZ_KEYMAP              (gdk_quartz_keymap_get_type ())
-#define GDK_QUARTZ_KEYMAP(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_QUARTZ_KEYMAP, GdkQuartzKeymap))
-#define GDK_QUARTZ_KEYMAP_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_QUARTZ_KEYMAP, GdkQuartzKeymapClass))
-#define GDK_IS_QUARTZ_KEYMAP(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_QUARTZ_KEYMAP))
-#define GDK_IS_QUARTZ_KEYMAP_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_QUARTZ_KEYMAP))
-#define GDK_QUARTZ_KEYMAP_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_QUARTZ_KEYMAP, GdkQuartzKeymapClass))
-
-#ifdef GTK_COMPILATION
-typedef struct _GdkQuartzKeymap GdkQuartzKeymap;
-#else
-typedef GdkKeymap GdkQuartzKeymap;
-#endif
-typedef struct _GdkQuartzKeymapClass GdkQuartzKeymapClass;
-
-GDK_AVAILABLE_IN_ALL
-GType gdk_quartz_keymap_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GDK_QUARTZ_KEYS_H__ */
diff --git a/gdk/quartz/gdkquartzmonitor.h b/gdk/quartz/gdkquartzmonitor.h
deleted file mode 100644 (file)
index a1ccda7..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * gdkquartzmonitor.h
- *
- * Copyright 2017 Tom Schoonjans
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_MONITOR_H__
-#define __GDK_QUARTZ_MONITOR_H__
-
-#if !defined (__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
-#endif
-
-#include <gdk/gdkmonitor.h>
-
-G_BEGIN_DECLS
-
-#define GDK_TYPE_QUARTZ_MONITOR           (gdk_quartz_monitor_get_type ())
-#define GDK_QUARTZ_MONITOR(object)        (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_QUARTZ_MONITOR, GdkQuartzMonitor))
-#define GDK_IS_QUARTZ_MONITOR(object)     (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_QUARTZ_MONITOR))
-
-typedef struct _GdkQuartzMonitor      GdkQuartzMonitor;
-typedef struct _GdkQuartzMonitorClass GdkQuartzMonitorClass;
-
-GDK_AVAILABLE_IN_ALL
-GType             gdk_quartz_monitor_get_type            (void) G_GNUC_CONST;
-
-
-G_END_DECLS
-
-#endif  /* __GDK_QUARTZ_MONITOR_H__ */
-
diff --git a/gdk/quartz/gdkquartzscreen.h b/gdk/quartz/gdkquartzscreen.h
deleted file mode 100644 (file)
index 3281ebc..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/* gdkquartzscreen.h
- *
- * Copyright (C) 2009, 2010  Kristian Rietveld  <kris@gtk.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_SCREEN_H__
-#define __GDK_QUARTZ_SCREEN_H__
-
-#if !defined(__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
-#endif
-
-G_BEGIN_DECLS
-
-#include <gdk/gdk.h>
-
-#define GDK_TYPE_QUARTZ_SCREEN              (gdk_quartz_screen_get_type ())
-#define GDK_QUARTZ_SCREEN(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_QUARTZ_SCREEN, GdkQuartzScreen))
-#define GDK_QUARTZ_SCREEN_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_QUARTZ_SCREEN, GdkQuartzScreenClass))
-#define GDK_IS_QUARTZ_SCREEN(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_QUARTZ_SCREEN))
-#define GDK_IS_QUARTZ_SCREEN_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_QUARTZ_SCREEN))
-#define GDK_QUARTZ_SCREEN_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_QUARTZ_SCREEN, GdkQuartzScreenClass))
-
-typedef struct _GdkQuartzScreen GdkQuartzScreen;
-typedef struct _GdkQuartzScreenClass GdkQuartzScreenClass;
-
-
-GDK_AVAILABLE_IN_ALL
-GType      gdk_quartz_screen_get_type (void);
-
-G_END_DECLS
-
-#endif /* _GDK_QUARTZ_SCREEN_H_ */
diff --git a/gdk/quartz/gdkquartzsurface.h b/gdk/quartz/gdkquartzsurface.h
deleted file mode 100644 (file)
index 6faa326..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* gdkquartzsurface.h
- *
- * Copyright (C) 2005  Imendio AB
- * Copyright (C) 2010  Kristian Rietveld  <kris@gtk.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_SURFACE_H__
-#define __GDK_QUARTZ_SURFACE_H__
-
-#if !defined (__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
-#endif
-
-#include <gdk/gdk.h>
-
-G_BEGIN_DECLS
-
-#define GDK_TYPE_QUARTZ_SURFACE              (gdk_quartz_surface_get_type ())
-#define GDK_QUARTZ_SURFACE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_QUARTZ_SURFACE, GdkQuartzSurface))
-#define GDK_QUARTZ_SURFACE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_QUARTZ_SURFACE, GdkQuartzSurfaceClass))
-#define GDK_IS_QUARTZ_SURFACE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_QUARTZ_SURFACE))
-#define GDK_IS_QUARTZ_SURFACE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_QUARTZ_SURFACE))
-#define GDK_QUARTZ_SURFACE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_QUARTZ_SURFACE, GdkQuartzSurfaceClass))
-
-#ifdef GTK_COMPILATION
-typedef struct _GdkQuartzSurface GdkQuartzSurface;
-#else
-typedef GdkSurface GdkQuartzSurface;
-#endif
-typedef struct _GdkQuartzSurfaceClass GdkQuartzSurfaceClass;
-
-GDK_AVAILABLE_IN_ALL
-GType     gdk_quartz_surface_get_type     (void);
-
-GDK_AVAILABLE_IN_ALL
-NSWindow *gdk_quartz_surface_get_nswindow (GdkSurface *window);
-GDK_AVAILABLE_IN_ALL
-NSView   *gdk_quartz_surface_get_nsview   (GdkSurface *window);
-
-G_END_DECLS
-
-#endif /* __GDK_QUARTZ_SURFACE_H__ */
diff --git a/gdk/quartz/gdkquartzutils.h b/gdk/quartz/gdkquartzutils.h
deleted file mode 100644 (file)
index 9909aa1..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* gdkquartzutils.h
- *
- * Copyright (C) 2005  Imendio AB
- * Copyright (C) 2010  Kristian Rietveld  <kris@gtk.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_UTILS_H__
-#define __GDK_QUARTZ_UTILS_H__
-
-#if !defined (__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
-#endif
-
-#include <gdk/gdk.h>
-
-G_BEGIN_DECLS
-
-GDK_AVAILABLE_IN_ALL
-NSImage  *gdk_quartz_pixbuf_to_ns_image_libgtk_only             (GdkPixbuf      *pixbuf);
-GDK_AVAILABLE_IN_ALL
-NSEvent  *gdk_quartz_event_get_nsevent                          (GdkEvent       *event);
-GDK_AVAILABLE_IN_ALL
-gunichar  gdk_quartz_get_key_equivalent                         (guint           key);
-
-G_END_DECLS
-
-#endif /* __GDK_QUARTZ_UTILS_H__ */
diff --git a/gdk/quartz/gdkscreen-quartz.c b/gdk/quartz/gdkscreen-quartz.c
deleted file mode 100644 (file)
index c1ab585..0000000
+++ /dev/null
@@ -1,288 +0,0 @@
-/* gdkscreen-quartz.c
- *
- * Copyright (C) 2005 Imendio AB
- * Copyright (C) 2009,2010  Kristian Rietveld  <kris@gtk.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include <gdk/gdk.h>
-
-#include "gdkprivate-quartz.h"
-#include "gdkdisplay-quartz.h"
-#include "gdkmonitor-quartz.h"
-
-/* A couple of notes about this file are in order.  In GDK, a
- * GdkScreen can contain multiple monitors.  A GdkScreen has an
- * associated root window, in which the monitors are placed.  The
- * root window "spans" all monitors.  The origin is at the top-left
- * corner of the root window.
- *
- * Cocoa works differently.  The system has a "screen" (NSScreen) for
- * each monitor that is connected (note the conflicting definitions
- * of screen).  The screen containing the menu bar is screen 0 and the
- * bottom-left corner of this screen is the origin of the "monitor
- * coordinate space".  All other screens are positioned according to this
- * origin.  If the menu bar is on a secondary screen (for example on
- * a monitor hooked up to a laptop), then this screen is screen 0 and
- * other monitors will be positioned according to the "secondary screen".
- * The main screen is the monitor that shows the window that is currently
- * active (has focus), the position of the menu bar does not have influence
- * on this!
- *
- * Upon start up and changes in the layout of screens, we calculate the
- * size of the GdkScreen root window that is needed to be able to place
- * all monitors in the root window.  Once that size is known, we iterate
- * over the monitors and translate their Cocoa position to a position
- * in the root window of the GdkScreen.  This happens below in the
- * function gdk_quartz_screen_calculate_layout().
- *
- * A Cocoa coordinate is always relative to the origin of the monitor
- * coordinate space.  Such coordinates are mapped to their respective
- * position in the GdkScreen root window (_gdk_quartz_surface_xy_to_gdk_xy)
- * and vice versa (_gdk_quartz_surface_gdk_xy_to_xy).  Both functions can
- * be found in gdksurface-quartz.c.  Note that Cocoa coordinates can have
- * negative values (in case a monitor is located left or below of screen 0),
- * but GDK coordinates can *not*!
- */
-
-static void  gdk_quartz_screen_dispose          (GObject         *object);
-static void  gdk_quartz_screen_finalize         (GObject         *object);
-static void  gdk_quartz_screen_calculate_layout (GdkQuartzScreen *screen);
-
-static void display_reconfiguration_callback (CGDirectDisplayID            display,
-                                              CGDisplayChangeSummaryFlags  flags,
-                                              void                        *userInfo);
-
-static gint get_mm_from_pixels (NSScreen *screen, int pixels);
-
-G_DEFINE_TYPE (GdkQuartzScreen, gdk_quartz_screen, G_TYPE_OBJECT);
-
-static void
-gdk_quartz_screen_init (GdkQuartzScreen *screen)
-{
-  NSDictionary *dd = [[[NSScreen screens] objectAtIndex:0] deviceDescription];
-  NSSize size = [[dd valueForKey:NSDeviceResolution] sizeValue];
-
-  gdk_quartz_screen_calculate_layout (screen);
-
-  CGDisplayRegisterReconfigurationCallback (display_reconfiguration_callback, screen);
-
-  quartz_screen->emit_monitors_changed = FALSE;
-}
-
-static void
-gdk_quartz_screen_dispose (GObject *object)
-{
-  GdkQuartzScreen *screen = GDK_QUARTZ_SCREEN (object);
-
-  if (screen->screen_changed_id)
-    {
-      g_source_remove (screen->screen_changed_id);
-      screen->screen_changed_id = 0;
-    }
-
-  CGDisplayRemoveReconfigurationCallback (display_reconfiguration_callback, screen);
-
-  G_OBJECT_CLASS (gdk_quartz_screen_parent_class)->dispose (object);
-}
-
-static void
-gdk_quartz_screen_finalize (GObject *object)
-{
-  G_OBJECT_CLASS (gdk_quartz_screen_parent_class)->finalize (object);
-}
-
-/* Protocol to build cleanly for OSX < 10.7 */
-@protocol ScaleFactor
-- (CGFloat) backingScaleFactor;
-@end
-
-static void
-gdk_quartz_screen_calculate_layout (GdkQuartzScreen *screen)
-{
-  NSArray *array;
-  int i;
-  int max_x, max_y;
-  GdkDisplay *display = screen->display;
-  GdkQuartzDisplay *display_quartz = GDK_QUARTZ_DISPLAY (display);
-
-  g_ptr_array_free (display_quartz->monitors, TRUE);
-  display_quartz->monitors = g_ptr_array_new_with_free_func (g_object_unref);
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  array = [NSScreen screens];
-
-  screen->width = 0;
-  screen->height = 0;
-  screen->min_x = 0;
-  screen->min_y = 0;
-  max_x = max_y = 0;
-
-  /* We determine the minimum and maximum x and y coordinates
-   * covered by the monitors.  From this we can deduce the width
-   * and height of the root screen.
-   */
-  for (i = 0; i < [array count]; i++)
-    {
-      GdkQuartzMonitor *monitor = g_object_new (GDK_TYPE_QUARTZ_MONITOR,
-                                                "display", display,
-                                                NULL);
-      g_ptr_array_add (display_quartz->monitors, monitor);
-      monitor->monitor_num = i;
-
-      NSRect rect = [[array objectAtIndex:i] frame];
-
-      screen->min_x = MIN (screen->min_x, rect.origin.x);
-      max_x = MAX (max_x, rect.origin.x + rect.size.width);
-
-      screen->min_y = MIN (screen->min_y, rect.origin.y);
-      max_y = MAX (max_y, rect.origin.y + rect.size.height);
-    }
-
-  screen->width = max_x - screen->min_x;
-  screen->height = max_y - screen->min_y;
-
-  for (i = 0; i < [array count] ; i++)
-    {
-      NSScreen *nsscreen;
-      NSRect rect;
-      GdkMonitor *monitor;
-
-      monitor = GDK_MONITOR(display_quartz->monitors->pdata[i]);
-      nsscreen = [array objectAtIndex:i];
-      rect = [nsscreen frame];
-
-      monitor->geometry.x = rect.origin.x - screen->min_x;
-      monitor->geometry.y
-          = screen->height - (rect.origin.y + rect.size.height) + screen->min_y;
-      monitor->geometry.width = rect.size.width;
-      monitor->geometry.height = rect.size.height;
-      if (gdk_quartz_osx_version() >= GDK_OSX_LION)
-        monitor->scale_factor = [(id <ScaleFactor>) nsscreen backingScaleFactor];
-      else
-        monitor->scale_factor = 1;
-      monitor->width_mm = get_mm_from_pixels(nsscreen, monitor->geometry.width);
-      monitor->height_mm = get_mm_from_pixels(nsscreen, monitor->geometry.height);
-      monitor->refresh_rate = 0; // unknown
-      monitor->manufacturer = NULL; // unknown
-      monitor->model = NULL; // unknown
-      monitor->subpixel_layout = GDK_SUBPIXEL_LAYOUT_UNKNOWN; // unknown
-    }
-
-  GDK_QUARTZ_RELEASE_POOL;
-}
-
-void
-_gdk_quartz_screen_update_window_sizes (GdkQuartzScreen *screen)
-{
-  GList *windows, *list;
-
-  /* The size of the root window is so that it can contain all
-   * monitors attached to this machine.  The monitors are laid out
-   * within this root window.  We calculate the size of the root window
-   * and the positions of the different monitors in gdkscreen-quartz.c.
-   *
-   * This data is updated when the monitor configuration is changed.
-   */
-
-  _gdk_root->x = 0;
-  _gdk_root->y = 0;
-  _gdk_root->abs_x = 0;
-  _gdk_root->abs_y = 0;
-
-  windows = get_toplevels ();
-  for (list = windows; list; list = list->next)
-    _gdk_quartz_surface_update_position (list->data);
-}
-
-static void
-process_display_reconfiguration (GdkQuartzScreen *screen)
-{
-  gdk_quartz_screen_calculate_layout (screen);
-
-  _gdk_quartz_screen_update_window_sizes (GDK_SCREEN (screen));
-}
-
-static gboolean
-screen_changed_idle (gpointer data)
-{
-  GdkQuartzScreen *screen = data;
-
-  process_display_reconfiguration (data);
-
-  screen->screen_changed_id = 0;
-
-  return FALSE;
-}
-
-static void
-display_reconfiguration_callback (CGDirectDisplayID            display,
-                                  CGDisplayChangeSummaryFlags  flags,
-                                  void                        *userInfo)
-{
-  GdkQuartzScreen *screen = userInfo;
-
-  if (flags & kCGDisplayBeginConfigurationFlag)
-    {
-      /* Ignore the begin configuration signal. */
-      return;
-    }
-  else
-    {
-      /* We save information about the changes, so we can emit
-       * ::monitors-changed when appropriate.  This signal must be
-       * emitted when the number, size of position of one of the
-       * monitors changes.
-       */
-      if (flags & kCGDisplayMovedFlag
-          || flags & kCGDisplayAddFlag
-          || flags & kCGDisplayRemoveFlag
-          || flags & kCGDisplayEnabledFlag
-          || flags & kCGDisplayDisabledFlag)
-        screen->emit_monitors_changed = TRUE;
-
-      /* At this point Cocoa does not know about the new screen data
-       * yet, so we delay our refresh into an idle handler.
-       */
-      if (!screen->screen_changed_id)
-        {
-          screen->screen_changed_id = g_idle_add (screen_changed_idle, screen);
-          g_source_set_name_by_id (screen->screen_changed_id, "[gtk] screen_changed_idle");
-        }
-    }
-}
-
-static gint
-get_mm_from_pixels (NSScreen *screen, int pixels)
-{
-  const float mm_per_inch = 25.4;
-  NSDictionary *dd = [[[NSScreen screens] objectAtIndex:0] deviceDescription];
-  NSSize size = [[dd valueForKey:NSDeviceResolution] sizeValue];
-  float dpi = size.width;
-  return (pixels / dpi) * mm_per_inch;
-}
-
-static void
-gdk_quartz_screen_class_init (GdkQuartzScreenClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-  object_class->dispose = gdk_quartz_screen_dispose;
-  object_class->finalize = gdk_quartz_screen_finalize;
-}
diff --git a/gdk/quartz/gdkscreen-quartz.h b/gdk/quartz/gdkscreen-quartz.h
deleted file mode 100644 (file)
index 1741393..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/* gdkscreen-quartz.h
- *
- * Copyright (C) 2009,2010  Kristian Rietveld  <kris@gtk.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_QUARTZ_SCREEN__
-#define __GDK_QUARTZ_SCREEN__
-
-G_BEGIN_DECLS
-
-struct _GdkQuartzScreen
-{
-  GObject parent_instance;
-
-  GdkDisplay *display;
-
-  /* Origin of "root window" in Cocoa coordinates */
-  gint min_x;
-  gint min_y;
-
-  gint width;
-  gint height;
-
-  guint screen_changed_id;
-
-  guint emit_monitors_changed : 1;
-};
-
-struct _GdkQuartzScreenClass
-{
-  GObjectClass parent_class;
-};
-
-G_END_DECLS
-
-#endif /* __GDK_QUARTZ_SCREEN__ */
diff --git a/gdk/quartz/gdkselection-quartz.c b/gdk/quartz/gdkselection-quartz.c
deleted file mode 100644 (file)
index 3f69d03..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* gdkselection-quartz.c
- *
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- * Copyright (C) 1998-2002 Tor Lillqvist
- * Copyright (C) 2005 Imendio AB
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include "gdkquartz.h"
-
-GdkAtom
-gdk_quartz_pasteboard_type_to_atom_libgtk_only (NSString *type)
-{
-  if ([type isEqualToString:NSStringPboardType])
-    return g_intern_static_string ("UTF8_STRING");
-  else if ([type isEqualToString:NSTIFFPboardType])
-    return g_intern_static_string ("image/tiff");
-  else if ([type isEqualToString:NSColorPboardType])
-    return g_intern_static_string ("application/x-color");
-  else if ([type isEqualToString:NSURLPboardType])
-    return g_intern_static_string ("text/uri-list");
-  else
-    return g_intern_string ([type UTF8String]);
-}
-
-NSString *
-gdk_quartz_target_to_pasteboard_type_libgtk_only (const char *target)
-{
-  if (strcmp (target, "UTF8_STRING") == 0)
-    return NSStringPboardType;
-  else if (strcmp (target, "image/tiff") == 0)
-    return NSTIFFPboardType;
-  else if (strcmp (target, "application/x-color") == 0)
-    return NSColorPboardType;
-  else if (strcmp (target, "text/uri-list") == 0)
-    return NSURLPboardType;
-  else
-    return [NSString stringWithUTF8String:target];
-}
-
-NSString *
-gdk_quartz_atom_to_pasteboard_type_libgtk_only (GdkAtom atom)
-{
-  const char *target = (const char *)atom;
-  NSString *ret = gdk_quartz_target_to_pasteboard_type_libgtk_only (target);
-
-  return ret;
-}
diff --git a/gdk/quartz/gdksurface-quartz.c b/gdk/quartz/gdksurface-quartz.c
deleted file mode 100644 (file)
index d16d26f..0000000
+++ /dev/null
@@ -1,2818 +0,0 @@
-/* gdksurface-quartz.c
- *
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- * Copyright (C) 2005-2007 Imendio AB
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include <gdk/gdk.h>
-#include <gdk/gdkdeviceprivate.h>
-#include <gdk/gdkdisplayprivate.h>
-
-#include "gdksurfaceimpl.h"
-#include "gdkprivate-quartz.h"
-#include "gdkglcontext-quartz.h"
-#include "gdkquartzscreen.h"
-#include "gdkquartzcursor.h"
-
-#include <Carbon/Carbon.h>
-#include <AvailabilityMacros.h>
-
-#include <sys/time.h>
-#include <cairo-quartz.h>
-
-static gpointer parent_class;
-static gpointer root_window_parent_class;
-
-static GSList   *update_nswindows;
-static gboolean  in_process_all_updates = FALSE;
-
-static GSList *main_window_stack;
-
-void _gdk_quartz_surface_flush (GdkSurfaceImplQuartz *surface_impl);
-
-typedef struct
-{
-  gint            x, y;
-  gint            width, height;
-  GdkWMDecoration decor;
-} FullscreenSavedGeometry;
-
-
-#ifndef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
-static FullscreenSavedGeometry *get_fullscreen_geometry (GdkSurface *window);
-#endif
-
-#define FULLSCREEN_DATA "fullscreen-data"
-
-static void update_toplevel_order (void);
-static void clear_toplevel_order  (void);
-
-#define SURFACE_IS_TOPLEVEL(window)      TRUE
-
-/*
- * GdkQuartzSurface
- */
-
-struct _GdkQuartzSurface
-{
-  GdkSurface parent;
-};
-
-struct _GdkQuartzSurfaceClass
-{
-  GdkSurfaceClass parent_class;
-};
-
-G_DEFINE_TYPE (GdkQuartzSurface, gdk_quartz_surface, GDK_TYPE_SURFACE);
-
-static void
-gdk_quartz_surface_class_init (GdkQuartzSurfaceClass *quartz_surface_class)
-{
-}
-
-static void
-gdk_quartz_surface_init (GdkQuartzSurface *quartz_surface)
-{
-}
-
-
-/*
- * GdkQuartzSurfaceImpl
- */
-
-NSView *
-gdk_quartz_surface_get_nsview (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window))
-    return NULL;
-
-  return ((GdkSurfaceImplQuartz *)window->impl)->view;
-}
-
-NSWindow *
-gdk_quartz_surface_get_nswindow (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window))
-    return NULL;
-
-  return ((GdkSurfaceImplQuartz *)window->impl)->toplevel;
-}
-
-static CGContextRef
-gdk_surface_impl_quartz_get_context (GdkSurfaceImplQuartz *surface_impl,
-                                   gboolean             antialias)
-{
-  CGContextRef cg_context;
-  CGSize scale;
-
-  if (GDK_SURFACE_DESTROYED (surface_impl->wrapper))
-    return NULL;
-
-  /* Lock focus when not called as part of a drawRect call. This
-   * is needed when called from outside "real" expose events, for
-   * example for synthesized expose events when realizing windows
-   * and for widgets that send fake expose events like the arrow
-   * buttons in spinbuttons or the position marker in rulers.
-   */
-  if (surface_impl->in_paint_rect_count == 0)
-    {
-      if (![surface_impl->view lockFocusIfCanDraw])
-        return NULL;
-    }
-  if (gdk_quartz_osx_version () < GDK_OSX_YOSEMITE)
-    cg_context = [[NSGraphicsContext currentContext] graphicsPort];
-  else
-    cg_context = [[NSGraphicsContext currentContext] CGContext];
-  if (!cg_context)
-    return NULL;
-  CGContextSaveGState (cg_context);
-  CGContextSetAllowsAntialiasing (cg_context, antialias);
-
-  /* Undo the default scaling transform, since we apply our own
-   * in gdk_quartz_ref_cairo_surface () */
-  scale = CGContextConvertSizeToDeviceSpace (cg_context,
-                                             CGSizeMake (1.0, 1.0));
-  CGContextScaleCTM (cg_context, 1.0 / scale.width, 1.0 / scale.height);
-
-  return cg_context;
-}
-
-static void
-gdk_surface_impl_quartz_release_context (GdkSurfaceImplQuartz *surface_impl,
-                                        CGContextRef         cg_context)
-{
-  CGContextRestoreGState (cg_context);
-  CGContextSetAllowsAntialiasing (cg_context, TRUE);
-
-  /* See comment in gdk_quartz_surface_get_context(). */
-  if (surface_impl->in_paint_rect_count == 0)
-    {
-      _gdk_quartz_surface_flush (surface_impl);
-      [surface_impl->view unlockFocus];
-    }
-}
-
-static void
-check_grab_destroy (GdkSurface *window)
-{
-  GList *devices = NULL, *l;
-  GdkDisplay *display = gdk_surface_get_display (window);
-  GdkSeat *seat;
-
-  seat = gdk_display_get_default_seat (display);
-
-  devices = g_list_prepend (devices, gdk_seat_get_keyboard (seat));
-  devices = g_list_prepend (devices, gdk_seat_get_pointer (seat));
-
-  for (l = devices; l; l = l->next)
-    {
-      GdkDeviceGrabInfo *grab;
-
-      grab = _gdk_display_get_last_device_grab (display, l->data);
-      if (grab && grab->native_surface == window)
-        {
-          /* Serials are always 0 in quartz, but for clarity: */
-          grab->serial_end = grab->serial_start;
-          grab->implicit_ungrab = TRUE;
-        }
-    }
-
-  g_list_free (devices);
-}
-
-static void
-gdk_surface_impl_quartz_finalize (GObject *object)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (object);
-
-  check_grab_destroy (GDK_SURFACE_IMPL_QUARTZ (object)->wrapper);
-
-  if (impl->transient_for)
-    g_object_unref (impl->transient_for);
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-/* Help preventing "beam sync penalty" where CG makes all graphics code
- * block until the next vsync if we try to flush (including call display on
- * a view) too often. We do this by limiting the manual flushing done
- * outside of expose calls to less than some frequency when measured over
- * the last 4 flushes. This is a bit arbitray, but seems to make it possible
- * for some quick manual flushes (such as gtkruler or gimp’s marching ants)
- * without hitting the max flush frequency.
- *
- * If drawable NULL, no flushing is done, only registering that a flush was
- * done externally.
- */
-void
-_gdk_quartz_surface_flush (GdkSurfaceImplQuartz *surface_impl)
-{
-  static struct timeval prev_tv;
-  static gint intervals[4];
-  static gint index;
-  struct timeval tv;
-  gint ms;
-
-  gettimeofday (&tv, NULL);
-  ms = (tv.tv_sec - prev_tv.tv_sec) * 1000 + (tv.tv_usec - prev_tv.tv_usec) / 1000;
-  intervals[index++ % 4] = ms;
-
-  if (surface_impl)
-    {
-      ms = intervals[0] + intervals[1] + intervals[2] + intervals[3];
-
-      /* ~25Hz on average. */
-      if (ms > 4*40)
-        {
-          if (surface_impl)
-            [surface_impl->toplevel flushWindow];
-
-          prev_tv = tv;
-        }
-    }
-  else
-    prev_tv = tv;
-}
-
-static cairo_user_data_key_t gdk_quartz_cairo_key;
-
-typedef struct {
-  GdkSurfaceImplQuartz  *surface_impl;
-  CGContextRef  cg_context;
-} GdkQuartzCairoSurfaceData;
-
-static void
-gdk_quartz_cairo_surface_destroy (void *data)
-{
-  GdkQuartzCairoSurfaceData *surface_data = data;
-
-  surface_data->surface_impl->cairo_surface = NULL;
-
-  gdk_quartz_surface_release_context (surface_data->surface_impl,
-                                     surface_data->cg_context);
-
-  g_free (surface_data);
-}
-
-static cairo_surface_t *
-gdk_quartz_create_cairo_surface (GdkSurfaceImplQuartz *impl,
-                                int                  width,
-                                int                  height)
-{
-  CGContextRef cg_context;
-  GdkQuartzCairoSurfaceData *surface_data;
-  cairo_surface_t *surface;
-
-  cg_context = gdk_quartz_surface_get_context (impl, TRUE);
-
-  surface_data = g_new (GdkQuartzCairoSurfaceData, 1);
-  surface_data->surface_impl = impl;
-  surface_data->cg_context = cg_context;
-
-  if (cg_context)
-    surface = cairo_quartz_surface_create_for_cg_context (cg_context,
-                                                          width, height);
-  else
-    surface = cairo_quartz_surface_create(CAIRO_FORMAT_ARGB32, width, height);
-
-  cairo_surface_set_user_data (surface, &gdk_quartz_cairo_key,
-                               surface_data,
-                               gdk_quartz_cairo_surface_destroy);
-
-  return surface;
-}
-
-static cairo_surface_t *
-gdk_quartz_ref_cairo_surface (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return NULL;
-
-  if (!impl->cairo_surface)
-    {
-      gint scale = gdk_surface_get_scale_factor (impl->wrapper);
-
-      impl->cairo_surface = 
-          gdk_quartz_create_cairo_surface (impl,
-                                           gdk_surface_get_width (impl->wrapper) * scale,
-                                           gdk_surface_get_height (impl->wrapper) * scale);
-
-      cairo_surface_set_device_scale (impl->cairo_surface, scale, scale);
-    }
-  else
-    cairo_surface_reference (impl->cairo_surface);
-
-  return impl->cairo_surface;
-}
-
-static void
-gdk_surface_impl_quartz_init (GdkSurfaceImplQuartz *impl)
-{
-  impl->type_hint = GDK_SURFACE_TYPE_HINT_NORMAL;
-}
-
-static gboolean
-gdk_surface_impl_quartz_begin_paint (GdkSurface *window)
-{
-  return FALSE;
-}
-
-static void
-gdk_quartz_surface_set_needs_display_in_region (GdkSurface    *window,
-                                               cairo_region_t    *region)
-{
-  GdkSurfaceImplQuartz *impl;
-  int i, n_rects;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (!impl->needs_display_region)
-    impl->needs_display_region = cairo_region_create ();
-
-  cairo_region_union (impl->needs_display_region, region);
-
-  n_rects = cairo_region_num_rectangles (region);
-  for (i = 0; i < n_rects; i++)
-    {
-      cairo_rectangle_int_t rect;
-      cairo_region_get_rectangle (region, i, &rect);
-      [impl->view setNeedsDisplayInRect:NSMakeRect (rect.x, rect.y,
-                                                    rect.width, rect.height)];
-    }
-}
-
-void
-_gdk_quartz_surface_process_updates_recurse (GdkSurface *window,
-                                            cairo_region_t *region)
-{
-  /* Make sure to only flush each toplevel at most once if we're called
-   * from process_all_updates.
-   */
-  if (in_process_all_updates)
-    {
-      GdkSurface *toplevel;
-
-      toplevel = gdk_surface_get_toplevel (window);
-      if (toplevel && SURFACE_IS_TOPLEVEL (toplevel))
-        {
-          GdkSurfaceImplQuartz *toplevel_impl;
-          NSWindow *nswindow;
-
-          toplevel_impl = (GdkSurfaceImplQuartz *)toplevel->impl;
-          nswindow = toplevel_impl->toplevel;
-
-          /* In theory, we could skip the flush disabling, since we only
-           * have one NSView.
-           */
-          if (nswindow && ![nswindow isFlushWindowDisabled]) 
-            {
-              [nswindow retain];
-              [nswindow disableFlushWindow];
-              update_nswindows = g_slist_prepend (update_nswindows, nswindow);
-            }
-        }
-    }
-
-  if (SURFACE_IS_TOPLEVEL (window))
-    gdk_quartz_surface_set_needs_display_in_region (window, region);
-  else
-    _gdk_surface_process_updates_recurse (window, region);
-
-  /* NOTE: I'm not sure if we should displayIfNeeded here. It slows down a
-   * lot (since it triggers the beam syncing) and things seem to work
-   * without it.
-   */
-}
-
-static const gchar *
-get_default_title (void)
-{
-  const char *title;
-
-  title = g_get_application_name ();
-  if (!title)
-    title = g_get_prgname ();
-
-  return title;
-}
-
-static void
-get_ancestor_coordinates_from_child (GdkSurface *child_window,
-                                    gint       child_x,
-                                    gint       child_y,
-                                    GdkSurface *ancestor_window, 
-                                    gint      *ancestor_x, 
-                                    gint      *ancestor_y)
-{
-  while (child_window != ancestor_window)
-    {
-      child_x += child_window->x;
-      child_y += child_window->y;
-
-      child_window = child_window->parent;
-    }
-
-  *ancestor_x = child_x;
-  *ancestor_y = child_y;
-}
-
-void
-_gdk_quartz_surface_debug_highlight (GdkSurface *window, gint number)
-{
-  gint x, y;
-  gint gx, gy;
-  GdkSurface *toplevel;
-  gint tx, ty;
-  static NSWindow *debug_window[10];
-  static NSRect old_rect[10];
-  NSRect rect;
-  NSColor *color;
-
-  g_return_if_fail (number >= 0 && number <= 9);
-
-  if (window == _gdk_root)
-    return;
-
-  if (window == NULL)
-    {
-      if (debug_window[number])
-        [debug_window[number] close];
-      debug_window[number] = NULL;
-
-      return;
-    }
-
-  toplevel = gdk_surface_get_toplevel (window);
-  get_ancestor_coordinates_from_child (window, 0, 0, toplevel, &x, &y);
-
-  gdk_surface_get_origin (toplevel, &tx, &ty);
-  x += tx;
-  y += ty;
-
-  _gdk_quartz_surface_gdk_xy_to_xy (x, y + window->height,
-                                   &gx, &gy);
-
-  rect = NSMakeRect (gx, gy, window->width, window->height);
-
-  if (debug_window[number] && NSEqualRects (rect, old_rect[number]))
-    return;
-
-  old_rect[number] = rect;
-
-  if (debug_window[number])
-    [debug_window[number] close];
-
-  debug_window[number] = [[NSWindow alloc] initWithContentRect:rect
-                                                     styleMask:NSBorderlessWindowMask
-                                                      backing:NSBackingStoreBuffered
-                                                        defer:NO];
-
-  switch (number)
-    {
-    case 0:
-      color = [NSColor redColor];
-      break;
-    case 1:
-      color = [NSColor blueColor];
-      break;
-    case 2:
-      color = [NSColor greenColor];
-      break;
-    case 3:
-      color = [NSColor yellowColor];
-      break;
-    case 4:
-      color = [NSColor brownColor];
-      break;
-    case 5:
-      color = [NSColor purpleColor];
-      break;
-    default:
-      color = [NSColor blackColor];
-      break;
-    }
-
-  [debug_window[number] setBackgroundColor:color];
-  [debug_window[number] setAlphaValue:0.4];
-  [debug_window[number] setOpaque:NO];
-  [debug_window[number] setReleasedWhenClosed:YES];
-  [debug_window[number] setIgnoresMouseEvents:YES];
-  [debug_window[number] setLevel:NSFloatingWindowLevel];
-
-  [debug_window[number] orderFront:nil];
-}
-
-gboolean
-_gdk_quartz_surface_is_ancestor (GdkSurface *ancestor,
-                                GdkSurface *window)
-{
-  if (ancestor == NULL || window == NULL)
-    return FALSE;
-
-  return (gdk_surface_get_parent (window) == ancestor ||
-          _gdk_quartz_surface_is_ancestor (ancestor, 
-                                          gdk_surface_get_parent (window)));
-}
-
-
-/* See notes on top of gdkscreen-quartz.c */
-void
-_gdk_quartz_surface_gdk_xy_to_xy (gint  gdk_x,
-                                 gint  gdk_y,
-                                 gint *ns_x,
-                                 gint *ns_y)
-{
-  GdkQuartzScreen *screen_quartz = GDK_QUARTZ_SCREEN (_gdk_screen);
-
-  if (ns_y)
-    *ns_y = screen_quartz->height - gdk_y + screen_quartz->min_y;
-
-  if (ns_x)
-    *ns_x = gdk_x + screen_quartz->min_x;
-}
-
-void
-_gdk_quartz_surface_xy_to_gdk_xy (gint  ns_x,
-                                 gint  ns_y,
-                                 gint *gdk_x,
-                                 gint *gdk_y)
-{
-  GdkQuartzScreen *screen_quartz = GDK_QUARTZ_SCREEN (_gdk_screen);
-
-  if (gdk_y)
-    *gdk_y = screen_quartz->height - ns_y + screen_quartz->min_y;
-
-  if (gdk_x)
-    *gdk_x = ns_x - screen_quartz->min_x;
-}
-
-void
-_gdk_quartz_surface_nspoint_to_gdk_xy (NSPoint  point,
-                                      gint    *x,
-                                      gint    *y)
-{
-  _gdk_quartz_surface_xy_to_gdk_xy (point.x, point.y,
-                                   x, y);
-}
-
-static GdkSurface *
-find_child_window_helper (GdkSurface *window,
-                         gint       x,
-                         gint       y,
-                         gint       x_offset,
-                         gint       y_offset,
-                          gboolean   get_toplevel)
-{
-  GdkSurfaceImplQuartz *impl;
-  GList *l;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (window == _gdk_root)
-    update_toplevel_order ();
-
-  for (l = impl->sorted_children; l; l = l->next)
-    {
-      GdkSurface *child = l->data;
-      GdkSurfaceImplQuartz *child_impl = GDK_SURFACE_IMPL_QUARTZ (child->impl);
-      int temp_x, temp_y;
-
-      if (!GDK_SURFACE_IS_MAPPED (child))
-       continue;
-
-      temp_x = x_offset + child->x;
-      temp_y = y_offset + child->y;
-
-      /* Special-case the root window. We have to include the title
-       * bar in the checks, otherwise the window below the title bar
-       * will be found i.e. events punch through. (If we can find a
-       * better way to deal with the events in gdkevents-quartz, this
-       * might not be needed.)
-       */
-      if (window == _gdk_root)
-        {
-          NSRect frame = NSMakeRect (0, 0, 100, 100);
-          NSRect content;
-          NSUInteger mask;
-          int titlebar_height;
-
-          mask = [child_impl->toplevel styleMask];
-
-          /* Get the title bar height. */
-          content = [NSWindow contentRectForFrameRect:frame
-                                            styleMask:mask];
-          titlebar_height = frame.size.height - content.size.height;
-
-          if (titlebar_height > 0 &&
-              x >= temp_x && y >= temp_y - titlebar_height &&
-              x < temp_x + child->width && y < temp_y)
-            {
-              /* The root means "unknown" i.e. a window not managed by
-               * GDK.
-               */
-              return (GdkSurface *)_gdk_root;
-            }
-        }
-
-      if ((!get_toplevel || (get_toplevel && window == _gdk_root)) &&
-          x >= temp_x && y >= temp_y &&
-         x < temp_x + child->width && y < temp_y + child->height)
-       {
-         /* Look for child windows. */
-         return find_child_window_helper (l->data,
-                                          x, y,
-                                          temp_x, temp_y,
-                                           get_toplevel);
-       }
-    }
-  
-  return window;
-}
-
-/* Given a GdkSurface and coordinates relative to it, returns the
- * innermost subwindow that contains the point. If the coordinates are
- * outside the passed in window, NULL is returned.
- */
-GdkSurface *
-_gdk_quartz_surface_find_child (GdkSurface *window,
-                              gint       x,
-                              gint       y,
-                               gboolean   get_toplevel)
-{
-  if (x >= 0 && y >= 0 && x < window->width && y < window->height)
-    return find_child_window_helper (window, x, y, 0, 0, get_toplevel);
-
-  return NULL;
-}
-
-
-void
-_gdk_quartz_surface_did_become_main (GdkSurface *window)
-{
-  main_window_stack = g_slist_remove (main_window_stack, window);
-
-  if (window->surface_type != GDK_SURFACE_TEMP)
-    main_window_stack = g_slist_prepend (main_window_stack, window);
-
-  clear_toplevel_order ();
-}
-
-void
-_gdk_quartz_surface_did_resign_main (GdkSurface *window)
-{
-  GdkSurface *new_window = NULL;
-
-  if (main_window_stack)
-    new_window = main_window_stack->data;
-  else
-    {
-      GList *toplevels;
-
-      toplevels = get_toplevels ();
-      if (toplevels)
-        new_window = toplevels->data;
-    }
-
-  if (new_window &&
-      new_window != window &&
-      GDK_SURFACE_IS_MAPPED (new_window) &&
-      SURFACE_IS_TOPLEVEL (new_window))
-    {
-      GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (new_window->impl);
-
-      [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
-    }
-
-  clear_toplevel_order ();
-}
-
-static NSScreen *
-get_nsscreen_for_point (gint x, gint y)
-{
-  int i;
-  NSArray *screens;
-  NSScreen *screen = NULL;
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  screens = [NSScreen screens];
-
-  for (i = 0; i < [screens count]; i++)
-    {
-      NSRect rect = [[screens objectAtIndex:i] frame];
-
-      if (x >= rect.origin.x && x <= rect.origin.x + rect.size.width &&
-          y >= rect.origin.y && y <= rect.origin.y + rect.size.height)
-        {
-          screen = [screens objectAtIndex:i];
-          break;
-        }
-    }
-
-  GDK_QUARTZ_RELEASE_POOL;
-
-  return screen;
-}
-
-void
-_gdk_quartz_display_create_surface_impl (GdkDisplay    *display,
-                                        GdkSurface     *window,
-                                        GdkSurface     *real_parent)
-{
-  GdkSurfaceImplQuartz *impl;
-  GdkSurfaceImplQuartz *parent_impl;
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  impl = g_object_new (GDK_TYPE_SURFACE_IMPL_QUARTZ, NULL);
-  window->impl = GDK_SURFACE_IMPL (impl);
-  impl->wrapper = window;
-
-  parent_impl = GDK_SURFACE_IMPL_QUARTZ (window->parent->impl);
-
-  switch (window->surface_type)
-    {
-    case GDK_SURFACE_TOPLEVEL:
-    case GDK_SURFACE_TEMP:
-      if (GDK_SURFACE_TYPE (window->parent) != GDK_SURFACE_ROOT)
-       {
-         /* The common code warns for this case */
-          parent_impl = GDK_SURFACE_IMPL_QUARTZ (_gdk_root->impl);
-       }
-    }
-
-  /* Maintain the z-ordered list of children. */
-  if (window->parent != _gdk_root)
-    parent_impl->sorted_children = g_list_prepend (parent_impl->sorted_children, window);
-  else
-    clear_toplevel_order ();
-
-  impl->view = NULL;
-
-  switch (window->surface_type)
-    {
-    case GDK_SURFACE_TOPLEVEL:
-    case GDK_SURFACE_TEMP:
-      {
-        NSScreen *screen;
-        NSRect screen_rect;
-        NSRect content_rect;
-        NSUInteger style_mask;
-        int nx, ny;
-
-        /* initWithContentRect will place on the mainScreen by default.
-         * We want to select the screen to place on ourselves.  We need
-         * to find the screen the window will be on and correct the
-         * content_rect coordinates to be relative to that screen.
-         */
-        _gdk_quartz_surface_gdk_xy_to_xy (window->x, window->y, &nx, &ny);
-
-        screen = get_nsscreen_for_point (nx, ny);
-        screen_rect = [screen frame];
-        nx -= screen_rect.origin.x;
-        ny -= screen_rect.origin.y;
-
-        content_rect = NSMakeRect (nx, ny - window->height,
-                                   window->width,
-                                   window->height);
-
-        if (window->surface_type == GDK_SURFACE_TEMP)
-          {
-            style_mask = NSBorderlessWindowMask;
-          }
-        else
-          {
-            style_mask = (NSTitledWindowMask |
-                          NSClosableWindowMask |
-                          NSMiniaturizableWindowMask |
-                          NSResizableWindowMask);
-          }
-
-       impl->toplevel = [[GdkQuartzNSWindow alloc] initWithContentRect:content_rect 
-                                                             styleMask:style_mask
-                                                               backing:NSBackingStoreBuffered
-                                                                 defer:NO
-                                                                  screen:screen];
-
-       gdk_surface_set_title (window, get_default_title ());
-  
-        [impl->toplevel setOpaque:NO];
-        [impl->toplevel setBackgroundColor:[NSColor clearColor]];
-
-        content_rect.origin.x = 0;
-        content_rect.origin.y = 0;
-
-       impl->view = [[GdkQuartzView alloc] initWithFrame:content_rect];
-       [impl->view setGdkSurface:window];
-       [impl->toplevel setContentView:impl->view];
-       [impl->view release];
-      }
-      break;
-
-    default:
-      g_assert_not_reached ();
-    }
-
-  GDK_QUARTZ_RELEASE_POOL;
-}
-
-void
-_gdk_quartz_surface_update_position (GdkSurface *window)
-{
-  NSRect frame_rect;
-  NSRect content_rect;
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  frame_rect = [impl->toplevel frame];
-  content_rect = [impl->toplevel contentRectForFrameRect:frame_rect];
-
-  _gdk_quartz_surface_xy_to_gdk_xy (content_rect.origin.x,
-                                   content_rect.origin.y + content_rect.size.height,
-                                   &window->x, &window->y);
-
-
-  GDK_QUARTZ_RELEASE_POOL;
-}
-
-void
-_gdk_quartz_surface_init_windowing (GdkDisplay *display)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  g_assert (_gdk_root == NULL);
-
-  _gdk_root = _gdk_display_create_window (display);
-
-  _gdk_root->impl = g_object_new (_gdk_root_surface_impl_quartz_get_type (), NULL);
-  _gdk_root->impl_surface = _gdk_root;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (_gdk_root->impl);
-
-  _gdk_quartz_screen_update_window_sizes (screen);
-
-  _gdk_root->state = 0; /* We don't want GDK_SURFACE_STATE_WITHDRAWN here */
-  _gdk_root->surface_type = GDK_SURFACE_ROOT;
-  _gdk_root->viewable = TRUE;
-
-  impl->wrapper = _gdk_root;
-}
-
-static void
-gdk_quartz_surface_destroy (GdkSurface *window,
-                           gboolean   recursing,
-                           gboolean   foreign_destroy)
-{
-  GdkSurfaceImplQuartz *impl;
-  GdkSurface *parent;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  main_window_stack = g_slist_remove (main_window_stack, window);
-
-  g_list_free (impl->sorted_children);
-  impl->sorted_children = NULL;
-
-  parent = window->parent;
-  if (parent)
-    {
-      GdkSurfaceImplQuartz *parent_impl = GDK_SURFACE_IMPL_QUARTZ (parent->impl);
-
-      parent_impl->sorted_children = g_list_remove (parent_impl->sorted_children, window);
-    }
-
-  if (impl->cairo_surface)
-    {
-      cairo_surface_finish (impl->cairo_surface);
-      cairo_surface_set_user_data (impl->cairo_surface, &gdk_quartz_cairo_key,
-                                  NULL, NULL);
-      impl->cairo_surface = NULL;
-    }
-
-  if (!recursing && !foreign_destroy)
-    {
-      GDK_QUARTZ_ALLOC_POOL;
-
-      if (impl->toplevel)
-       [impl->toplevel close];
-      else if (impl->view)
-       [impl->view removeFromSuperview];
-
-      GDK_QUARTZ_RELEASE_POOL;
-    }
-}
-
-/* FIXME: This might be possible to simplify with client-side windows. Also
- * note that already_mapped is not used yet, see the x11 backend.
-*/
-static void
-gdk_surface_quartz_show (GdkSurface *window, gboolean already_mapped)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  gboolean focus_on_map;
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  if (!GDK_SURFACE_IS_MAPPED (window))
-    focus_on_map = window->focus_on_map;
-  else
-    focus_on_map = TRUE;
-
-  if (SURFACE_IS_TOPLEVEL (window) && impl->toplevel)
-    {
-      gboolean make_key;
-
-      make_key = (window->accept_focus && focus_on_map &&
-                  window->surface_type != GDK_SURFACE_TEMP);
-
-      [(GdkQuartzNSWindow*)impl->toplevel showAndMakeKey:make_key];
-      clear_toplevel_order ();
-
-      _gdk_quartz_events_send_map_event (window);
-    }
-  else
-    {
-      [impl->view setHidden:NO];
-    }
-
-  [impl->view setNeedsDisplay:YES];
-
-  gdk_synthesize_surface_state (window, GDK_SURFACE_STATE_WITHDRAWN, 0);
-
-  if (window->state & GDK_SURFACE_STATE_MAXIMIZED)
-    gdk_surface_maximize (window);
-
-  if (window->state & GDK_SURFACE_STATE_MINIMIZED)
-    gdk_surface_minimize (window);
-
-  if (impl->transient_for && !GDK_SURFACE_DESTROYED (impl->transient_for))
-    _gdk_quartz_surface_attach_to_parent (window);
-
-  GDK_QUARTZ_RELEASE_POOL;
-}
-
-/* Temporarily unsets the parent window, if the window is a
- * transient. 
- */
-void
-_gdk_quartz_surface_detach_from_parent (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  
-  g_return_if_fail (impl->toplevel != NULL);
-
-  if (impl->transient_for && !GDK_SURFACE_DESTROYED (impl->transient_for))
-    {
-      GdkSurfaceImplQuartz *parent_impl;
-
-      parent_impl = GDK_SURFACE_IMPL_QUARTZ (impl->transient_for->impl);
-      [parent_impl->toplevel removeChildWindow:impl->toplevel];
-      clear_toplevel_order ();
-    }
-}
-
-/* Re-sets the parent window, if the window is a transient. */
-void
-_gdk_quartz_surface_attach_to_parent (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  
-  g_return_if_fail (impl->toplevel != NULL);
-
-  if (impl->transient_for && !GDK_SURFACE_DESTROYED (impl->transient_for))
-    {
-      GdkSurfaceImplQuartz *parent_impl;
-
-      parent_impl = GDK_SURFACE_IMPL_QUARTZ (impl->transient_for->impl);
-      [parent_impl->toplevel addChildWindow:impl->toplevel ordered:NSWindowAbove];
-      clear_toplevel_order ();
-    }
-}
-
-void
-gdk_surface_quartz_hide (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  /* Make sure we're not stuck in fullscreen mode. */
-#ifndef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
-  if (get_fullscreen_geometry (window))
-    SetSystemUIMode (kUIModeNormal, 0);
-#endif
-
-  _gdk_surface_clear_update_area (window);
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (SURFACE_IS_TOPLEVEL (window)) 
-    {
-     /* Update main window. */
-      main_window_stack = g_slist_remove (main_window_stack, window);
-      if ([NSApp mainWindow] == impl->toplevel)
-        _gdk_quartz_surface_did_resign_main (window);
-
-      if (impl->transient_for)
-        _gdk_quartz_surface_detach_from_parent (window);
-
-      [(GdkQuartzNSWindow*)impl->toplevel hide];
-    }
-  else if (impl->view)
-    {
-      [impl->view setHidden:YES];
-    }
-}
-
-void
-gdk_surface_quartz_withdraw (GdkSurface *window)
-{
-  gdk_surface_hide (window);
-}
-
-static void
-move_resize_window_internal (GdkSurface *window,
-                            gint       x,
-                            gint       y,
-                            gint       width,
-                            gint       height)
-{
-  GdkSurfaceImplQuartz *impl;
-  GdkRectangle old_visible;
-  GdkRectangle new_visible;
-  GdkRectangle scroll_rect;
-  cairo_region_t *old_region;
-  cairo_region_t *expose_region;
-  NSSize delta;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if ((x == -1 || (x == window->x)) &&
-      (y == -1 || (y == window->y)) &&
-      (width == -1 || (width == window->width)) &&
-      (height == -1 || (height == window->height)))
-    {
-      return;
-    }
-
-  if (!impl->toplevel)
-    {
-      /* The previously visible area of this window in a coordinate
-       * system rooted at the origin of this window.
-       */
-      old_visible.x = -window->x;
-      old_visible.y = -window->y;
-
-      old_visible.width = window->width;
-      old_visible.height = window->height;
-    }
-
-  if (x != -1)
-    {
-      delta.width = x - window->x;
-      window->x = x;
-    }
-  else
-    {
-      delta.width = 0;
-    }
-
-  if (y != -1)
-    {
-      delta.height = y - window->y;
-      window->y = y;
-    }
-  else
-    {
-      delta.height = 0;
-    }
-
-  if (width != -1)
-    window->width = width;
-
-  if (height != -1)
-    window->height = height;
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  if (impl->toplevel)
-    {
-      NSRect content_rect;
-      NSRect frame_rect;
-      gint gx, gy;
-
-      _gdk_quartz_surface_gdk_xy_to_xy (window->x, window->y + window->height,
-                                       &gx, &gy);
-
-      content_rect = NSMakeRect (gx, gy, window->width, window->height);
-
-      frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
-      [impl->toplevel setFrame:frame_rect display:YES];
-    }
-  else 
-    {
-      NSRect nsrect;
-
-      nsrect = NSMakeRect (window->x, window->y, window->width, window->height);
-
-      /* The newly visible area of this window in a coordinate
-       * system rooted at the origin of this window.
-       */
-      new_visible.x = -window->x;
-      new_visible.y = -window->y;
-      new_visible.width = old_visible.width;   /* parent has not changed size */
-      new_visible.height = old_visible.height; /* parent has not changed size */
-
-      expose_region = cairo_region_create_rectangle (&new_visible);
-      old_region = cairo_region_create_rectangle (&old_visible);
-      cairo_region_subtract (expose_region, old_region);
-
-      /* Determine what (if any) part of the previously visible
-       * part of the window can be copied without a redraw
-       */
-      scroll_rect = old_visible;
-      scroll_rect.x -= delta.width;
-      scroll_rect.y -= delta.height;
-      gdk_rectangle_intersect (&scroll_rect, &old_visible, &scroll_rect);
-
-      if (!cairo_region_is_empty (expose_region))
-        {
-          if (scroll_rect.width != 0 && scroll_rect.height != 0)
-            {
-              [impl->view scrollRect:NSMakeRect (scroll_rect.x,
-                                                 scroll_rect.y,
-                                                 scroll_rect.width,
-                                                 scroll_rect.height)
-                                     by:delta];
-            }
-
-          [impl->view setFrame:nsrect];
-
-          gdk_quartz_surface_set_needs_display_in_region (window, expose_region);
-        }
-      else
-        {
-          [impl->view setFrame:nsrect];
-          [impl->view setNeedsDisplay:YES];
-        }
-
-      cairo_region_destroy (expose_region);
-      cairo_region_destroy (old_region);
-    }
-
-  GDK_QUARTZ_RELEASE_POOL;
-}
-
-static inline void
-window_quartz_move (GdkSurface *window,
-                    gint       x,
-                    gint       y)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
-    return;
-
-  move_resize_window_internal (window, x, y, -1, -1);
-}
-
-static inline void
-window_quartz_resize (GdkSurface *window,
-                      gint       width,
-                      gint       height)
-{
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (window->state & GDK_SURFACE_STATE_FULLSCREEN)
-    return;
-
-  if (width < 1)
-    width = 1;
-  if (height < 1)
-    height = 1;
-
-  move_resize_window_internal (window, -1, -1, width, height);
-}
-
-static inline void
-window_quartz_move_resize (GdkSurface *window,
-                           gint       x,
-                           gint       y,
-                           gint       width,
-                           gint       height)
-{
-  if (width < 1)
-    width = 1;
-  if (height < 1)
-    height = 1;
-
-  move_resize_window_internal (window, x, y, width, height);
-}
-
-static void
-gdk_surface_quartz_toplevel_resize (GdkSurface *surface,
-                                    gint        width,
-                                    gint        height)
-{
-  window_quartz_resize (window, width, height);
-}
-
-static void
-gdk_quartz_surface_layout_popup (GdkSurface     *surface,
-                                 int             width,
-                                 int             height,
-                                 GdkPopupLayout *layout)
-{
-  GdkRectangle final_rect;
-  int x, y;
-
-  gdk_surface_layout_popup_helper (surface,
-                                   width,
-                                   height,
-                                   layout,
-                                   &final_rect);
-
-  gdk_surface_get_origin (surface->parent, &x, &y);
-  x += final_rect.x;
-  y += final_rect.y;
-
-  if (final_rect.width != surface->width ||
-      final_rect.height != surface->height)
-    {
-      move_resize_window_internal (surface,
-                                   x,
-                                   y,
-                                   final_rect.width,
-                                   final_rect.height);
-    }
-  else
-    {
-      window_quartz_move (surface, x, y);
-    }
-}
-
-static void
-show_popup (GdkSurface *surface)
-{
-  gdk_surface_raise (surface);
-  gdk_synthesize_surface_state (surface, GDK_SURFACE_STATE_WITHDRAWN, 0);
-  _gdk_surface_update_viewable (surface);
-  gdk_quartz_surface_show (surface, FALSE);
-  gdk_surface_invalidate_rect (surface, NULL);
-}
-
-static void
-show_grabbing_popup (GdkSeat    *seat,
-                     GdkSurface *surface,
-                     gpointer    user_data)
-{
-  show_popup (surface);
-}
-
-static gboolean
-gdk_quartz_surface_present_popup (GdkSurface     *surface,
-                                  int             width,
-                                  int             height,
-                                  GdkPopupLayout *layout)
-{
-  gdk_quartz_surface_layout_popup (surface, width, height, layout);
-
-  if (GDK_SURFACE_IS_MAPPED (surface))
-    return TRUE;
-
-  if (surface->autohide)
-    {
-      gdk_seat_grab (gdk_display_get_default_seat (surface->display),
-                     surface,
-                     GDK_SEAT_CAPABILITY_ALL,
-                     TRUE,
-                     NULL, NULL,
-                     show_grabbing_popup, NULL);
-    }
-  else
-    {
-      show_popup (surface);
-    }
-
-  return GDK_SURFACE_IS_MAPPED (surface);
-}
-
-/* Get the toplevel ordering from NSApp and update our own list. We do
- * this on demand since the NSApp’s list is not up to date directly
- * after we get windowDidBecomeMain.
- */
-static void
-update_toplevel_order (void)
-{
-  GdkSurfaceImplQuartz *root_impl;
-  NSEnumerator *enumerator;
-  id nswindow;
-  GList *toplevels = NULL;
-
-  root_impl = GDK_SURFACE_IMPL_QUARTZ (_gdk_root->impl);
-
-  if (root_impl->sorted_children)
-    return;
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  enumerator = [[NSApp orderedWindows] objectEnumerator];
-  while ((nswindow = [enumerator nextObject]))
-    {
-      GdkSurface *window;
-
-      if (![[nswindow contentView] isKindOfClass:[GdkQuartzView class]])
-        continue;
-
-      window = [(GdkQuartzView *)[nswindow contentView] gdkSurface];
-      toplevels = g_list_prepend (toplevels, window);
-    }
-
-  GDK_QUARTZ_RELEASE_POOL;
-
-  root_impl->sorted_children = g_list_reverse (toplevels);
-}
-
-static void
-clear_toplevel_order (void)
-{
-  GdkSurfaceImplQuartz *root_impl;
-
-  root_impl = GDK_SURFACE_IMPL_QUARTZ (_gdk_root->impl);
-
-  g_list_free (root_impl->sorted_children);
-  root_impl->sorted_children = NULL;
-}
-
-static void
-gdk_surface_quartz_raise (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (SURFACE_IS_TOPLEVEL (window))
-    {
-      GdkSurfaceImplQuartz *impl;
-
-      impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-      [impl->toplevel orderFront:impl->toplevel];
-
-      clear_toplevel_order ();
-    }
-  else
-    {
-      GdkSurface *parent = window->parent;
-
-      if (parent)
-        {
-          GdkSurfaceImplQuartz *impl;
-
-          impl = (GdkSurfaceImplQuartz *)parent->impl;
-
-          impl->sorted_children = g_list_remove (impl->sorted_children, window);
-          impl->sorted_children = g_list_prepend (impl->sorted_children, window);
-        }
-    }
-}
-
-static void
-gdk_surface_quartz_lower (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  if (SURFACE_IS_TOPLEVEL (window))
-    {
-      GdkSurfaceImplQuartz *impl;
-
-      impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-      [impl->toplevel orderBack:impl->toplevel];
-
-      clear_toplevel_order ();
-    }
-  else
-    {
-      GdkSurface *parent = window->parent;
-
-      if (parent)
-        {
-          GdkSurfaceImplQuartz *impl;
-
-          impl = (GdkSurfaceImplQuartz *)parent->impl;
-
-          impl->sorted_children = g_list_remove (impl->sorted_children, window);
-          impl->sorted_children = g_list_append (impl->sorted_children, window);
-        }
-    }
-}
-
-static void
-gdk_surface_quartz_get_geometry (GdkSurface *window,
-                                gint      *x,
-                                gint      *y,
-                                gint      *width,
-                                gint      *height)
-{
-  GdkSurfaceImplQuartz *impl;
-  NSRect ns_rect;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  if (window == _gdk_root)
-    {
-      if (x) 
-        *x = 0;
-      if (y) 
-        *y = 0;
-
-      if (width) 
-        *width = window->width;
-      if (height)
-        *height = window->height;
-    }
-  else if (SURFACE_IS_TOPLEVEL (window))
-    {
-      ns_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
-
-      /* This doesn't work exactly as in X. There doesn't seem to be a
-       * way to get the coords relative to the parent window (usually
-       * the window frame), but that seems useless except for
-       * borderless windows where it's relative to the root window. So
-       * we return (0, 0) (should be something like (0, 22)) for
-       * windows with borders and the root relative coordinates
-       * otherwise.
-       */
-      if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
-        {
-          _gdk_quartz_surface_xy_to_gdk_xy (ns_rect.origin.x,
-                                           ns_rect.origin.y + ns_rect.size.height,
-                                           x, y);
-        }
-      else 
-        {
-          if (x)
-            *x = 0;
-          if (y)
-            *y = 0;
-        }
-
-      if (width)
-        *width = ns_rect.size.width;
-      if (height)
-        *height = ns_rect.size.height;
-    }
-  else
-    {
-      ns_rect = [impl->view frame];
-      
-      if (x)
-        *x = ns_rect.origin.x;
-      if (y)
-        *y = ns_rect.origin.y;
-      if (width)
-        *width  = ns_rect.size.width;
-      if (height)
-        *height = ns_rect.size.height;
-    }
-}
-
-static void
-gdk_surface_quartz_get_root_coords (GdkSurface *window,
-                                   gint       x,
-                                   gint       y,
-                                   gint      *root_x,
-                                   gint      *root_y)
-{
-  int tmp_x = 0, tmp_y = 0;
-  GdkSurface *toplevel;
-  NSRect content_rect;
-  GdkSurfaceImplQuartz *impl;
-
-  if (GDK_SURFACE_DESTROYED (window)) 
-    {
-      if (root_x)
-       *root_x = 0;
-      if (root_y)
-       *root_y = 0;
-      
-      return;
-    }
-
-  if (window == _gdk_root)
-    {
-      if (root_x)
-        *root_x = x;
-      if (root_y)
-        *root_y = y;
-
-      return;
-    }
-  
-  toplevel = gdk_surface_get_toplevel (window);
-  impl = GDK_SURFACE_IMPL_QUARTZ (toplevel->impl);
-
-  content_rect = [impl->toplevel contentRectForFrameRect:[impl->toplevel frame]];
-
-  _gdk_quartz_surface_xy_to_gdk_xy (content_rect.origin.x,
-                                   content_rect.origin.y + content_rect.size.height,
-                                   &tmp_x, &tmp_y);
-
-  tmp_x += x;
-  tmp_y += y;
-
-  while (window != toplevel)
-    {
-      tmp_x += window->x;
-      tmp_y += window->y;
-
-      window = window->parent;
-    }
-
-  if (root_x)
-    *root_x = tmp_x;
-  if (root_y)
-    *root_y = tmp_y;
-}
-
-/* Returns coordinates relative to the passed in window. */
-static GdkSurface *
-gdk_surface_quartz_get_device_state_helper (GdkSurface       *window,
-                                           GdkDevice       *device,
-                                           gdouble         *x,
-                                           gdouble         *y,
-                                           GdkModifierType *mask)
-{
-  NSPoint point;
-  gint x_tmp, y_tmp;
-  GdkSurface *toplevel;
-  GdkSurface *found_window;
-
-  g_return_val_if_fail (window == NULL || GDK_IS_SURFACE (window), NULL);
-
-  if (GDK_SURFACE_DESTROYED (window))
-    {
-      *x = 0;
-      *y = 0;
-      *mask = 0;
-      return NULL;
-    }
-  
-  toplevel = gdk_surface_get_toplevel (window);
-
-  *mask = _gdk_quartz_events_get_current_keyboard_modifiers () |
-      _gdk_quartz_events_get_current_mouse_modifiers ();
-
-  /* Get the y coordinate, needs to be flipped. */
-  if (window == _gdk_root)
-    {
-      point = [NSEvent mouseLocation];
-      _gdk_quartz_surface_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
-    }
-  else
-    {
-      GdkSurfaceImplQuartz *impl;
-      NSWindow *nswindow;
-
-      impl = GDK_SURFACE_IMPL_QUARTZ (toplevel->impl);
-      nswindow = impl->toplevel;
-
-      point = [nswindow mouseLocationOutsideOfEventStream];
-
-      x_tmp = point.x;
-      y_tmp = toplevel->height - point.y;
-
-      window = (GdkSurface *)toplevel;
-    }
-
-  found_window = _gdk_quartz_surface_find_child (window, x_tmp, y_tmp,
-                                                FALSE);
-
-  /* We never return the root window. */
-  if (found_window == _gdk_root)
-    found_window = NULL;
-
-  *x = x_tmp;
-  *y = y_tmp;
-
-  return found_window;
-}
-
-static gboolean
-gdk_surface_quartz_get_device_state (GdkSurface       *window,
-                                    GdkDevice       *device,
-                                    gdouble          *x,
-                                    gdouble          *y,
-                                    GdkModifierType *mask)
-{
-  return gdk_surface_quartz_get_device_state_helper (window,
-                                                    device,
-                                                    x, y, mask) != NULL;
-}
-
-static void
-gdk_quartz_surface_set_geometry_hints (GdkSurface         *window,
-                                      const GdkGeometry *geometry,
-                                      GdkSurfaceHints     geom_mask)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  g_return_if_fail (geometry != NULL);
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-  
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  if (!impl->toplevel)
-    return;
-
-  if (geom_mask & GDK_HINT_POS)
-    {
-      /* FIXME: Implement */
-    }
-
-  if (geom_mask & GDK_HINT_USER_POS)
-    {
-      /* FIXME: Implement */
-    }
-
-  if (geom_mask & GDK_HINT_USER_SIZE)
-    {
-      /* FIXME: Implement */
-    }
-  
-  if (geom_mask & GDK_HINT_MIN_SIZE)
-    {
-      NSSize size;
-
-      size.width = geometry->min_width;
-      size.height = geometry->min_height;
-
-      [impl->toplevel setContentMinSize:size];
-    }
-  
-  if (geom_mask & GDK_HINT_MAX_SIZE)
-    {
-      NSSize size;
-
-      size.width = geometry->max_width;
-      size.height = geometry->max_height;
-
-      [impl->toplevel setContentMaxSize:size];
-    }
-  
-  if (geom_mask & GDK_HINT_BASE_SIZE)
-    {
-      /* FIXME: Implement */
-    }
-  
-  if (geom_mask & GDK_HINT_RESIZE_INC)
-    {
-      NSSize size;
-
-      size.width = geometry->width_inc;
-      size.height = geometry->height_inc;
-
-      [impl->toplevel setContentResizeIncrements:size];
-    }
-  
-  if (geom_mask & GDK_HINT_ASPECT)
-    {
-      NSSize size;
-
-      if (geometry->min_aspect != geometry->max_aspect)
-        {
-          g_warning ("Only equal minimum and maximum aspect ratios are supported on Mac OS. Using minimum aspect ratio...");
-        }
-
-      size.width = geometry->min_aspect;
-      size.height = 1.0;
-
-      [impl->toplevel setContentAspectRatio:size];
-    }
-
-  if (geom_mask & GDK_HINT_WIN_GRAVITY)
-    {
-      /* FIXME: Implement */
-    }
-}
-
-static void
-gdk_quartz_surface_set_title (GdkSurface   *window,
-                             const gchar *title)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  g_return_if_fail (title != NULL);
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (impl->toplevel)
-    {
-      GDK_QUARTZ_ALLOC_POOL;
-      [impl->toplevel setTitle:[NSString stringWithUTF8String:title]];
-      GDK_QUARTZ_RELEASE_POOL;
-    }
-}
-
-static void
-gdk_quartz_surface_set_startup_id (GdkSurface   *window,
-                                  const gchar *startup_id)
-{
-  /* FIXME: Implement? */
-}
-
-static void
-gdk_quartz_surface_set_transient_for (GdkSurface *window,
-                                     GdkSurface *parent)
-{
-  GdkSurfaceImplQuartz *surface_impl;
-  GdkSurfaceImplQuartz *parent_impl;
-
-  if (GDK_SURFACE_DESTROYED (window)  || GDK_SURFACE_DESTROYED (parent) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-
-  surface_impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  if (!surface_impl->toplevel)
-    return;
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  if (surface_impl->transient_for)
-    {
-      _gdk_quartz_surface_detach_from_parent (window);
-
-      g_object_unref (surface_impl->transient_for);
-      surface_impl->transient_for = NULL;
-    }
-
-  parent_impl = GDK_SURFACE_IMPL_QUARTZ (parent->impl);
-  if (parent_impl->toplevel)
-    {
-      /* We save the parent because it needs to be unset/reset when
-       * hiding and showing the window. 
-       */
-
-      /* We don't set transients for tooltips, they are already
-       * handled by the window level being the top one. If we do, then
-       * the parent window will be brought to the top just because the
-       * tooltip is, which is not what we want.
-       */
-      if (gdk_surface_get_type_hint (window) != GDK_SURFACE_TYPE_HINT_TOOLTIP)
-        {
-          surface_impl->transient_for = g_object_ref (parent);
-
-          /* We only add the window if it is shown, otherwise it will
-           * be shown unconditionally here. If it is not shown, the
-           * window will be added in show() instead.
-           */
-          if (!(window->state & GDK_SURFACE_STATE_WITHDRAWN))
-            _gdk_quartz_surface_attach_to_parent (window);
-        }
-    }
-  
-  GDK_QUARTZ_RELEASE_POOL;
-}
-
-static void
-gdk_surface_quartz_input_shape_combine_region (GdkSurface       *window,
-                                              const cairo_region_t *shape_region,
-                                              gint             offset_x,
-                                              gint             offset_y)
-{
-  /* FIXME: Implement */
-}
-
-static void
-gdk_quartz_surface_set_accept_focus (GdkSurface *window,
-                                    gboolean accept_focus)
-{
-  window->accept_focus = accept_focus != FALSE;
-}
-
-static void
-gdk_quartz_surface_set_focus_on_map (GdkSurface *window,
-                                    gboolean focus_on_map)
-{
-  window->focus_on_map = focus_on_map != FALSE;
-}
-
-static void
-gdk_quartz_surface_focus (GdkSurface *window,
-                         guint32    timestamp)
-{
-  GdkSurfaceImplQuartz *impl;
-       
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-
-  if (window->accept_focus && window->surface_type != GDK_SURFACE_TEMP)
-    {
-      GDK_QUARTZ_ALLOC_POOL;
-      [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
-      clear_toplevel_order ();
-      GDK_QUARTZ_RELEASE_POOL;
-    }
-}
-
-static gint
-surface_type_hint_to_level (GdkSurfaceTypeHint hint)
-{
-  /*  the order in this switch statement corresponds to the actual
-   *  stacking order: the first group is top, the last group is bottom
-   */
-  switch (hint)
-    {
-    case GDK_SURFACE_TYPE_HINT_POPUP_MENU:
-    case GDK_SURFACE_TYPE_HINT_COMBO:
-    case GDK_SURFACE_TYPE_HINT_DND:
-    case GDK_SURFACE_TYPE_HINT_TOOLTIP:
-      return NSPopUpMenuWindowLevel;
-
-    case GDK_SURFACE_TYPE_HINT_NOTIFICATION:
-    case GDK_SURFACE_TYPE_HINT_SPLASHSCREEN:
-      return NSStatusWindowLevel;
-
-    case GDK_SURFACE_TYPE_HINT_MENU: /* Torn-off menu */
-    case GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
-      return NSTornOffMenuWindowLevel;
-
-    case GDK_SURFACE_TYPE_HINT_DOCK:
-      return NSFloatingWindowLevel; /* NSDockWindowLevel is deprecated, and not replaced */
-
-    case GDK_SURFACE_TYPE_HINT_UTILITY:
-    case GDK_SURFACE_TYPE_HINT_DIALOG:  /* Dialog window */
-    case GDK_SURFACE_TYPE_HINT_NORMAL:  /* Normal toplevel window */
-    case GDK_SURFACE_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
-      return NSNormalWindowLevel;
-
-    case GDK_SURFACE_TYPE_HINT_DESKTOP:
-      return kCGDesktopWindowLevelKey; /* doesn't map to any real Cocoa model */
-
-    default:
-      break;
-    }
-
-  return NSNormalWindowLevel;
-}
-
-static gboolean
-surface_type_hint_to_shadow (GdkSurfaceTypeHint hint)
-{
-  switch (hint)
-    {
-    case GDK_SURFACE_TYPE_HINT_NORMAL:  /* Normal toplevel window */
-    case GDK_SURFACE_TYPE_HINT_DIALOG:  /* Dialog window */
-    case GDK_SURFACE_TYPE_HINT_DOCK:
-    case GDK_SURFACE_TYPE_HINT_UTILITY:
-    case GDK_SURFACE_TYPE_HINT_MENU: /* Torn-off menu */
-    case GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU: /* Menu from menubar */
-    case GDK_SURFACE_TYPE_HINT_SPLASHSCREEN:
-    case GDK_SURFACE_TYPE_HINT_POPUP_MENU:
-    case GDK_SURFACE_TYPE_HINT_COMBO:
-    case GDK_SURFACE_TYPE_HINT_NOTIFICATION:
-    case GDK_SURFACE_TYPE_HINT_TOOLTIP:
-      return TRUE;
-
-    case GDK_SURFACE_TYPE_HINT_TOOLBAR: /* Window used to implement toolbars */
-    case GDK_SURFACE_TYPE_HINT_DESKTOP: /* N/A */
-    case GDK_SURFACE_TYPE_HINT_DND:
-      break;
-
-    default:
-      break;
-    }
-
-  return FALSE;
-}
-
-static gboolean
-surface_type_hint_to_hides_on_deactivate (GdkSurfaceTypeHint hint)
-{
-  switch (hint)
-    {
-    case GDK_SURFACE_TYPE_HINT_UTILITY:
-    case GDK_SURFACE_TYPE_HINT_MENU: /* Torn-off menu */
-    case GDK_SURFACE_TYPE_HINT_SPLASHSCREEN:
-    case GDK_SURFACE_TYPE_HINT_NOTIFICATION:
-    case GDK_SURFACE_TYPE_HINT_TOOLTIP:
-      return TRUE;
-
-    default:
-      break;
-    }
-
-  return FALSE;
-}
-
-static void
-_gdk_quartz_surface_update_has_shadow (GdkSurfaceImplQuartz *impl)
-{
-    gboolean has_shadow;
-
-    /* In case there is any shadow set we have to turn off the
-     * NSWindow setHasShadow as the system drawn ones wont match our
-     * window boundary anymore */
-    has_shadow = (surface_type_hint_to_shadow (impl->type_hint) && !impl->shadow_max);
-
-    [impl->toplevel setHasShadow: has_shadow];
-}
-
-static void
-gdk_quartz_surface_set_type_hint (GdkSurface        *window,
-                                 GdkSurfaceTypeHint hint)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  impl->type_hint = hint;
-
-  /* Match the documentation, only do something if we're not mapped yet. */
-  if (GDK_SURFACE_IS_MAPPED (window))
-    return;
-
-  _gdk_quartz_surface_update_has_shadow (impl);
-  [impl->toplevel setLevel: surface_type_hint_to_level (hint)];
-  [impl->toplevel setHidesOnDeactivate: surface_type_hint_to_hides_on_deactivate (hint)];
-}
-
-static GdkSurfaceTypeHint
-gdk_quartz_surface_get_type_hint (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return GDK_SURFACE_TYPE_HINT_NORMAL;
-  
-  return GDK_SURFACE_IMPL_QUARTZ (window->impl)->type_hint;
-}
-
-static void
-gdk_quartz_surface_set_modal_hint (GdkSurface *window,
-                                  gboolean   modal)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-
-  /* FIXME: Implement */
-}
-
-static void
-gdk_quartz_surface_begin_resize_drag (GdkSurface     *window,
-                                     GdkSurfaceEdge  edge,
-                                     GdkDevice     *device,
-                                     gint           button,
-                                     gint           root_x,
-                                     gint           root_y,
-                                     guint32        timestamp)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (!impl->toplevel)
-    {
-      g_warning ("Can't call gdk_surface_begin_resize_drag on non-toplevel window");
-      return;
-    }
-
-  [(GdkQuartzNSWindow *)impl->toplevel beginManualResize:edge];
-}
-
-static void
-gdk_quartz_surface_begin_move_drag (GdkSurface *window,
-                                   GdkDevice *device,
-                                   gint       button,
-                                   gint       root_x,
-                                   gint       root_y,
-                                   guint32    timestamp)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (!impl->toplevel)
-    {
-      g_warning ("Can't call gdk_surface_begin_move_drag on non-toplevel window");
-      return;
-    }
-
-  [(GdkQuartzNSWindow *)impl->toplevel beginManualMove];
-}
-
-static void
-gdk_quartz_surface_set_icon_list (GdkSurface *window,
-                                 GList     *surfaces)
-{
-  /* FIXME: Implement */
-}
-
-static void
-gdk_quartz_surface_get_frame_extents (GdkSurface    *window,
-                                     GdkRectangle *rect)
-{
-  GdkSurface *toplevel;
-  GdkSurfaceImplQuartz *impl;
-  NSRect ns_rect;
-
-  g_return_if_fail (rect != NULL);
-
-
-  rect->x = 0;
-  rect->y = 0;
-  rect->width = 1;
-  rect->height = 1;
-  
-  toplevel = gdk_surface_get_toplevel (window);
-  impl = GDK_SURFACE_IMPL_QUARTZ (toplevel->impl);
-
-  ns_rect = [impl->toplevel frame];
-
-  _gdk_quartz_surface_xy_to_gdk_xy (ns_rect.origin.x,
-                                   ns_rect.origin.y + ns_rect.size.height,
-                                   &rect->x, &rect->y);
-
-  rect->width = ns_rect.size.width;
-  rect->height = ns_rect.size.height;
-}
-
-/* Fake protocol to make gcc think that it's OK to call setStyleMask
-   even if it isn't. We check to make sure before actually calling
-   it. */
-
-@protocol CanSetStyleMask
-- (void)setStyleMask:(int)mask;
-@end
-
-static void
-gdk_quartz_surface_set_decorations (GdkSurface       *window,
-                           GdkWMDecoration  decorations)
-{
-  GdkSurfaceImplQuartz *impl;
-  NSUInteger old_mask, new_mask;
-  NSView *old_view;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (decorations == 0 || GDK_SURFACE_TYPE (window) == GDK_SURFACE_TEMP ||
-      impl->type_hint == GDK_SURFACE_TYPE_HINT_SPLASHSCREEN )
-    {
-      new_mask = NSBorderlessWindowMask;
-    }
-  else
-    {
-      /* FIXME: Honor other GDK_DECOR_* flags. */
-      new_mask = (NSTitledWindowMask | NSClosableWindowMask |
-                    NSMiniaturizableWindowMask | NSResizableWindowMask);
-    }
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  old_mask = [impl->toplevel styleMask];
-
-  if (old_mask != new_mask)
-    {
-      NSRect rect;
-
-      old_view = [[impl->toplevel contentView] retain];
-
-      rect = [impl->toplevel frame];
-
-      /* Properly update the size of the window when the titlebar is
-       * added or removed.
-       */
-      if (old_mask == NSBorderlessWindowMask &&
-          new_mask != NSBorderlessWindowMask)
-        {
-          rect = [NSWindow frameRectForContentRect:rect styleMask:new_mask];
-
-        }
-      else if (old_mask != NSBorderlessWindowMask &&
-               new_mask == NSBorderlessWindowMask)
-        {
-          rect = [NSWindow contentRectForFrameRect:rect styleMask:old_mask];
-        }
-
-      /* Note, before OS 10.6 there doesn't seem to be a way to change this
-       * without recreating the toplevel. From 10.6 onward, a simple call to
-       * setStyleMask takes care of most of this, except for ensuring that the
-       * title is set.
-       */
-      if ([impl->toplevel respondsToSelector:@selector(setStyleMask:)])
-        {
-          NSString *title = [impl->toplevel title];
-
-          [(id<CanSetStyleMask>)impl->toplevel setStyleMask:new_mask];
-
-          /* It appears that unsetting and then resetting NSTitledWindowMask
-           * does not reset the title in the title bar as might be expected.
-           *
-           * In theory we only need to set this if new_mask includes
-           * NSTitledWindowMask. This behaved extremely oddly when
-           * conditionalized upon that and since it has no side effects (i.e.
-           * if NSTitledWindowMask is not requested, the title will not be
-           * displayed) just do it unconditionally. We also must null check
-           * 'title' before setting it to avoid crashing.
-           */
-          if (title)
-            [impl->toplevel setTitle:title];
-        }
-      else
-        {
-          NSString *title = [impl->toplevel title];
-          NSColor *bg = [impl->toplevel backgroundColor];
-          NSScreen *screen = [impl->toplevel screen];
-
-          /* Make sure the old window is closed, recall that releasedWhenClosed
-           * is set on GdkQuartzSurfaces.
-           */
-          [impl->toplevel close];
-
-          impl->toplevel = [[GdkQuartzNSWindow alloc] initWithContentRect:rect
-                                                                styleMask:new_mask
-                                                                  backing:NSBackingStoreBuffered
-                                                                    defer:NO
-                                                                   screen:screen];
-          _gdk_quartz_surface_update_has_shadow (impl);
-
-          [impl->toplevel setLevel: surface_type_hint_to_level (impl->type_hint)];
-          if (title)
-            [impl->toplevel setTitle:title];
-          [impl->toplevel setBackgroundColor:bg];
-          [impl->toplevel setHidesOnDeactivate: surface_type_hint_to_hides_on_deactivate (impl->type_hint)];
-          [impl->toplevel setContentView:old_view];
-        }
-
-      if (new_mask == NSBorderlessWindowMask)
-        {
-          [impl->toplevel setContentSize:rect.size];
-          [impl->toplevel setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
-        }
-      else
-        [impl->toplevel setFrame:rect display:YES];
-
-      /* Invalidate the window shadow for non-opaque views that have shadow
-       * enabled, to get the shadow shape updated.
-       */
-      if (![old_view isOpaque] && [impl->toplevel hasShadow])
-        [(GdkQuartzView*)old_view setNeedsInvalidateShadow:YES];
-
-      [old_view release];
-    }
-
-  GDK_QUARTZ_RELEASE_POOL;
-}
-
-static gboolean
-gdk_quartz_surface_get_decorations (GdkSurface       *window,
-                                   GdkWMDecoration *decorations)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return FALSE;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (decorations)
-    {
-      /* Borderless is 0, so we can't check it as a bit being set. */
-      if ([impl->toplevel styleMask] == NSBorderlessWindowMask)
-        {
-          *decorations = 0;
-        }
-      else
-        {
-          /* FIXME: Honor the other GDK_DECOR_* flags. */
-          *decorations = GDK_DECOR_ALL;
-        }
-    }
-
-  return TRUE;
-}
-
-static void
-gdk_quartz_surface_stick (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-}
-
-static void
-gdk_quartz_surface_unstick (GdkSurface *window)
-{
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-}
-
-static void
-gdk_quartz_surface_maximize (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-  gboolean maximized;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  maximized = gdk_surface_get_state (window) & GDK_SURFACE_STATE_MAXIMIZED;
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {
-      GDK_QUARTZ_ALLOC_POOL;
-
-      if (impl->toplevel && !maximized)
-        [impl->toplevel zoom:nil];
-
-      GDK_QUARTZ_RELEASE_POOL;
-    }
-}
-
-static void
-gdk_quartz_surface_unmaximize (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-  gboolean maximized;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  maximized = gdk_surface_get_state (window) & GDK_SURFACE_STATE_MAXIMIZED;
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {
-      GDK_QUARTZ_ALLOC_POOL;
-
-      if (impl->toplevel && maximized)
-        [impl->toplevel zoom:nil];
-
-      GDK_QUARTZ_RELEASE_POOL;
-    }
-}
-
-static void
-gdk_quartz_surface_minimize (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {
-      GDK_QUARTZ_ALLOC_POOL;
-
-      if (impl->toplevel)
-       [impl->toplevel miniaturize:nil];
-
-      GDK_QUARTZ_RELEASE_POOL;
-    }
-  else
-    {
-      gdk_synthesize_surface_state (window, 0, GDK_SURFACE_STATE_MINIMIZED);
-    }
-}
-
-static void
-gdk_quartz_surface_unminimize (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (GDK_SURFACE_IS_MAPPED (window))
-    {
-      GDK_QUARTZ_ALLOC_POOL;
-
-      if (impl->toplevel)
-       [impl->toplevel deminiaturize:nil];
-
-      GDK_QUARTZ_RELEASE_POOL;
-    }
-  else
-    {
-      gdk_synthesize_surface_state (window, GDK_SURFACE_STATE_MINIMIZED, 0);
-    }
-}
-
-#ifdef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
-
-static gboolean
-window_is_fullscreen (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  return ([impl->toplevel styleMask] & NSFullScreenWindowMask) != 0;
-}
-
-static void
-gdk_quartz_surface_fullscreen (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (!window_is_fullscreen (window))
-    [impl->toplevel toggleFullScreen:nil];
-}
-
-static void
-gdk_quartz_surface_unfullscreen (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (window_is_fullscreen (window))
-    [impl->toplevel toggleFullScreen:nil];
-}
-
-void
-_gdk_quartz_surface_update_fullscreen_state (GdkSurface *window)
-{
-  gboolean is_fullscreen;
-  gboolean was_fullscreen;
-
-  is_fullscreen = window_is_fullscreen (window);
-  was_fullscreen = (gdk_surface_get_state (window) & GDK_SURFACE_STATE_FULLSCREEN) != 0;
-
-  if (is_fullscreen != was_fullscreen)
-    {
-      if (is_fullscreen)
-        gdk_synthesize_surface_state (window, 0, GDK_SURFACE_STATE_FULLSCREEN);
-      else
-        gdk_synthesize_surface_state (window, GDK_SURFACE_STATE_FULLSCREEN, 0);
-    }
-}
-
-#else
-
-static FullscreenSavedGeometry *
-get_fullscreen_geometry (GdkSurface *window)
-{
-  return g_object_get_data (G_OBJECT (window), FULLSCREEN_DATA);
-}
-
-static void
-gdk_quartz_surface_fullscreen (GdkSurface *window)
-{
-  FullscreenSavedGeometry *geometry;
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  NSRect frame;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-
-  geometry = get_fullscreen_geometry (window);
-  if (!geometry)
-    {
-      geometry = g_new (FullscreenSavedGeometry, 1);
-
-      geometry->x = window->x;
-      geometry->y = window->y;
-      geometry->width = window->width;
-      geometry->height = window->height;
-
-      if (!gdk_quartz_surface_get_decorations (window, &geometry->decor))
-        geometry->decor = GDK_DECOR_ALL;
-
-      g_object_set_data_full (G_OBJECT (window),
-                              FULLSCREEN_DATA, geometry, 
-                              g_free);
-
-      gdk_quartz_surface_set_decorations (window, 0);
-
-      frame = [[impl->toplevel screen] frame];
-      move_resize_window_internal (window,
-                                   0, 0, 
-                                   frame.size.width, frame.size.height);
-      [impl->toplevel setContentSize:frame.size];
-      [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
-
-      clear_toplevel_order ();
-    }
-
-  SetSystemUIMode (kUIModeAllHidden, kUIOptionAutoShowMenuBar);
-
-  gdk_synthesize_surface_state (window, 0, GDK_SURFACE_STATE_FULLSCREEN);
-}
-
-static void
-gdk_quartz_surface_unfullscreen (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  FullscreenSavedGeometry *geometry;
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-
-  geometry = get_fullscreen_geometry (window);
-  if (geometry)
-    {
-      SetSystemUIMode (kUIModeNormal, 0);
-
-      move_resize_window_internal (window,
-                                   geometry->x,
-                                   geometry->y,
-                                   geometry->width,
-                                   geometry->height);
-      
-      gdk_quartz_surface_set_decorations (window, geometry->decor);
-
-      g_object_set_data (G_OBJECT (window), FULLSCREEN_DATA, NULL);
-
-      [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
-      clear_toplevel_order ();
-
-      gdk_synthesize_surface_state (window, GDK_SURFACE_STATE_FULLSCREEN, 0);
-    }
-}
-
-#endif
-
-static void
-gdk_quartz_surface_set_keep_above (GdkSurface *window,
-                                  gboolean   setting)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  gint level;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-
-  level = surface_type_hint_to_level (gdk_surface_get_type_hint (window));
-  
-  /* Adjust normal window level by one if necessary. */
-  [impl->toplevel setLevel: level + (setting ? 1 : 0)];
-}
-
-static void
-gdk_quartz_surface_set_keep_below (GdkSurface *window,
-                                  gboolean   setting)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-  gint level;
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-  
-  level = surface_type_hint_to_level (gdk_surface_get_type_hint (window));
-  
-  /* Adjust normal window level by one if necessary. */
-  [impl->toplevel setLevel: level - (setting ? 1 : 0)];
-}
-
-static void
-gdk_quartz_surface_destroy_notify (GdkSurface *window)
-{
-  check_grab_destroy (window);
-}
-
-static void
-gdk_quartz_surface_set_opacity (GdkSurface *window,
-                               gdouble    opacity)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (SURFACE_IS_TOPLEVEL (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-
-  if (opacity < 0)
-    opacity = 0;
-  else if (opacity > 1)
-    opacity = 1;
-
-  [impl->toplevel setAlphaValue: opacity];
-}
-
-static void
-gdk_quartz_surface_set_shadow_width (GdkSurface *window,
-                                    gint       left,
-                                    gint       right,
-                                    gint       top,
-                                    gint       bottom)
-{
-  GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  g_return_if_fail (GDK_IS_SURFACE (window));
-  g_return_if_fail (SURFACE_IS_TOPLEVEL (window));
-
-  if (GDK_SURFACE_DESTROYED (window) ||
-      !SURFACE_IS_TOPLEVEL (window))
-    return;
-
-  impl->shadow_top = top;
-  impl->shadow_max = MAX (MAX (left, right), MAX (top, bottom));
-  _gdk_quartz_surface_update_has_shadow (impl);
-}
-
-/* Protocol to build cleanly for OSX < 10.7 */
-@protocol ScaleFactor
-- (CGFloat) backingScaleFactor;
-@end
-
-static gint
-gdk_quartz_surface_get_scale_factor (GdkSurface *window)
-{
-  GdkSurfaceImplQuartz *impl;
-
-  if (GDK_SURFACE_DESTROYED (window))
-    return 1;
-
-  impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
-
-  if (impl->toplevel != NULL && gdk_quartz_osx_version() >= GDK_OSX_LION)
-    return [(id <ScaleFactor>) impl->toplevel backingScaleFactor];
-
-  return 1;
-}
-
-static void
-gdk_surface_impl_quartz_class_init (GdkSurfaceImplQuartzClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GdkSurfaceImplClass *impl_class = GDK_SURFACE_IMPL_CLASS (klass);
-  GdkSurfaceImplQuartzClass *impl_quartz_class = GDK_SURFACE_IMPL_QUARTZ_CLASS (klass);
-
-  parent_class = g_type_class_peek_parent (klass);
-
-  object_class->finalize = gdk_surface_impl_quartz_finalize;
-
-  impl_class->ref_cairo_surface = gdk_quartz_ref_cairo_surface;
-  impl_class->show = gdk_surface_quartz_show;
-  impl_class->hide = gdk_surface_quartz_hide;
-  impl_class->withdraw = gdk_surface_quartz_withdraw;
-  impl_class->raise = gdk_surface_quartz_raise;
-  impl_class->lower = gdk_surface_quartz_lower;
-  impl_class->toplevel_resize = gdk_surface_quartz_toplevel_resize;
-  impl_class->present_popup = gdk_quartz_surface_present_popup;
-  impl_class->get_geometry = gdk_surface_quartz_get_geometry;
-  impl_class->get_root_coords = gdk_surface_quartz_get_root_coords;
-  impl_class->get_device_state = gdk_surface_quartz_get_device_state;
-  impl_class->input_shape_combine_region = gdk_surface_quartz_input_shape_combine_region;
-  impl_class->destroy = gdk_quartz_surface_destroy;
-  impl_class->begin_paint = gdk_surface_impl_quartz_begin_paint;
-  impl_class->get_scale_factor = gdk_quartz_surface_get_scale_factor;
-
-  impl_class->focus = gdk_quartz_surface_focus;
-  impl_class->set_type_hint = gdk_quartz_surface_set_type_hint;
-  impl_class->get_type_hint = gdk_quartz_surface_get_type_hint;
-  impl_class->set_modal_hint = gdk_quartz_surface_set_modal_hint;
-  impl_class->set_geometry_hints = gdk_quartz_surface_set_geometry_hints;
-  impl_class->set_title = gdk_quartz_surface_set_title;
-  impl_class->set_startup_id = gdk_quartz_surface_set_startup_id;
-  impl_class->set_transient_for = gdk_quartz_surface_set_transient_for;
-  impl_class->get_frame_extents = gdk_quartz_surface_get_frame_extents;
-  impl_class->set_accept_focus = gdk_quartz_surface_set_accept_focus;
-  impl_class->set_focus_on_map = gdk_quartz_surface_set_focus_on_map;
-  impl_class->set_icon_list = gdk_quartz_surface_set_icon_list;
-  impl_class->minimize = gdk_quartz_surface_minimize;
-  impl_class->unminimize = gdk_quartz_surface_unminimize;
-  impl_class->stick = gdk_quartz_surface_stick;
-  impl_class->unstick = gdk_quartz_surface_unstick;
-  impl_class->maximize = gdk_quartz_surface_maximize;
-  impl_class->unmaximize = gdk_quartz_surface_unmaximize;
-  impl_class->fullscreen = gdk_quartz_surface_fullscreen;
-  impl_class->unfullscreen = gdk_quartz_surface_unfullscreen;
-  impl_class->set_keep_above = gdk_quartz_surface_set_keep_above;
-  impl_class->set_keep_below = gdk_quartz_surface_set_keep_below;
-  impl_class->begin_resize_drag = gdk_quartz_surface_begin_resize_drag;
-  impl_class->begin_move_drag = gdk_quartz_surface_begin_move_drag;
-  impl_class->set_opacity = gdk_quartz_surface_set_opacity;
-  impl_class->set_shadow_width = gdk_quartz_surface_set_shadow_width;
-  impl_class->destroy_notify = gdk_quartz_surface_destroy_notify;
-  impl_class->drag_begin = _gdk_quartz_surface_drag_begin;
-  impl_class->process_updates_recurse = _gdk_quartz_surface_process_updates_recurse;
-
-  impl_class->create_gl_context = gdk_quartz_surface_create_gl_context;
-
-  impl_quartz_class->get_context = gdk_surface_impl_quartz_get_context;
-  impl_quartz_class->release_context = gdk_surface_impl_quartz_release_context;
-}
-
-GType
-_gdk_surface_impl_quartz_get_type (void)
-{
-  static GType object_type = 0;
-
-  if (!object_type)
-    {
-      const GTypeInfo object_info =
-       {
-         sizeof (GdkSurfaceImplQuartzClass),
-         (GBaseInitFunc) NULL,
-         (GBaseFinalizeFunc) NULL,
-         (GClassInitFunc) gdk_surface_impl_quartz_class_init,
-         NULL,           /* class_finalize */
-         NULL,           /* class_data */
-         sizeof (GdkSurfaceImplQuartz),
-         0,              /* n_preallocs */
-         (GInstanceInitFunc) gdk_surface_impl_quartz_init,
-       };
-
-      object_type = g_type_register_static (GDK_TYPE_SURFACE_IMPL,
-                                            "GdkSurfaceImplQuartz",
-                                            &object_info, 0);
-    }
-
-  return object_type;
-}
-
-CGContextRef
-gdk_quartz_surface_get_context (GdkSurfaceImplQuartz  *window,
-                               gboolean             antialias)
-{
-  if (!GDK_SURFACE_IMPL_QUARTZ_GET_CLASS (window)->get_context)
-    {
-      g_warning ("%s doesn't implement GdkSurfaceImplQuartzClass::get_context()",
-                 G_OBJECT_TYPE_NAME (window));
-      return NULL;
-    }
-
-  return GDK_SURFACE_IMPL_QUARTZ_GET_CLASS (window)->get_context (window, antialias);
-}
-
-void
-gdk_quartz_surface_release_context (GdkSurfaceImplQuartz  *window,
-                                   CGContextRef          cg_context)
-{
-  if (!GDK_SURFACE_IMPL_QUARTZ_GET_CLASS (window)->release_context)
-    {
-      g_warning ("%s doesn't implement GdkSurfaceImplQuartzClass::release_context()",
-                 G_OBJECT_TYPE_NAME (window));
-      return;
-    }
-
-  GDK_SURFACE_IMPL_QUARTZ_GET_CLASS (window)->release_context (window, cg_context);
-}
-
-
-
-static CGContextRef
-gdk_root_surface_impl_quartz_get_context (GdkSurfaceImplQuartz *window,
-                                         gboolean             antialias)
-{
-  CGColorSpaceRef colorspace;
-  CGContextRef cg_context;
-  GdkSurfaceImplQuartz *surface_impl = GDK_SURFACE_IMPL_QUARTZ (window);
-
-  if (GDK_SURFACE_DESTROYED (surface_impl->wrapper))
-    return NULL;
-
-  /* We do not have the notion of a root window on OS X.  We fake this
-   * by creating a 1x1 bitmap and return a context to that.
-   */
-  colorspace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);
-  cg_context = CGBitmapContextCreate (NULL,
-                                      1, 1, 8, 4, colorspace,
-                                      kCGImageAlphaPremultipliedLast);
-  CGColorSpaceRelease (colorspace);
-
-  return cg_context;
-}
-
-static void
-gdk_root_surface_impl_quartz_release_context (GdkSurfaceImplQuartz *window,
-                                             CGContextRef         cg_context)
-{
-  CGContextRelease (cg_context);
-}
-
-static void
-gdk_root_surface_impl_quartz_class_init (GdkRootWindowImplQuartzClass *klass)
-{
-  GdkSurfaceImplQuartzClass *window_quartz_class = GDK_SURFACE_IMPL_QUARTZ_CLASS (klass);
-
-  root_window_parent_class = g_type_class_peek_parent (klass);
-
-  window_quartz_class->get_context = gdk_root_surface_impl_quartz_get_context;
-  window_quartz_class->release_context = gdk_root_surface_impl_quartz_release_context;
-}
-
-static void
-gdk_root_surface_impl_quartz_init (GdkRootWindowImplQuartz *impl)
-{
-}
-
-GType
-_gdk_root_surface_impl_quartz_get_type (void)
-{
-  static GType object_type = 0;
-
-  if (!object_type)
-    {
-      const GTypeInfo object_info =
-        {
-          sizeof (GdkRootWindowImplQuartzClass),
-          (GBaseInitFunc) NULL,
-          (GBaseFinalizeFunc) NULL,
-          (GClassInitFunc) gdk_root_surface_impl_quartz_class_init,
-          NULL,           /* class_finalize */
-          NULL,           /* class_data */
-          sizeof (GdkRootWindowImplQuartz),
-          0,              /* n_preallocs */
-          (GInstanceInitFunc) gdk_root_surface_impl_quartz_init,
-        };
-
-      object_type = g_type_register_static (GDK_TYPE_SURFACE_IMPL_QUARTZ,
-                                            "GdkRootWindowQuartz",
-                                            &object_info, 0);
-    }
-
-  return object_type;
-}
-
-GList *
-get_toplevels (void)
-{
-  update_toplevel_order ();
-  return GDK_SURFACE_IMPL_QUARTZ (_gdk_root->impl)->sorted_children;
-}
diff --git a/gdk/quartz/gdksurface-quartz.h b/gdk/quartz/gdksurface-quartz.h
deleted file mode 100644 (file)
index 74ccfc2..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/* gdkdrawable-quartz.h
- *
- * Copyright (C) 2005 Imendio AB
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GDK_SURFACE_QUARTZ_H__
-#define __GDK_SURFACE_QUARTZ_H__
-
-#import <gdk/quartz/GdkQuartzView.h>
-#import <gdk/quartz/GdkQuartzNSWindow.h>
-#include "gdk/gdksurfaceimpl.h"
-
-G_BEGIN_DECLS
-
-/* Window implementation for Quartz
- */
-
-typedef struct _GdkSurfaceImplQuartz GdkSurfaceImplQuartz;
-typedef struct _GdkSurfaceImplQuartzClass GdkSurfaceImplQuartzClass;
-
-#define GDK_TYPE_SURFACE_IMPL_QUARTZ              (_gdk_surface_impl_quartz_get_type ())
-#define GDK_SURFACE_IMPL_QUARTZ(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SURFACE_IMPL_QUARTZ, GdkSurfaceImplQuartz))
-#define GDK_SURFACE_IMPL_QUARTZ_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SURFACE_IMPL_QUARTZ, GdkSurfaceImplQuartzClass))
-#define GDK_IS_SURFACE_IMPL_QUARTZ(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SURFACE_IMPL_QUARTZ))
-#define GDK_IS_SURFACE_IMPL_QUARTZ_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SURFACE_IMPL_QUARTZ))
-#define GDK_SURFACE_IMPL_QUARTZ_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SURFACE_IMPL_QUARTZ, GdkSurfaceImplQuartzClass))
-
-struct _GdkSurfaceImplQuartz
-{
-  GdkSurfaceImpl parent_instance;
-
-  GdkSurface *wrapper;
-
-  NSWindow *toplevel;
-  NSTrackingRectTag tracking_rect;
-  GdkQuartzView *view;
-
-  GdkSurfaceTypeHint type_hint;
-
-  gint in_paint_rect_count;
-
-  GdkSurface *transient_for;
-
-  /* Sorted by z-order */
-  GList *sorted_children;
-
-  cairo_region_t *needs_display_region;
-
-  cairo_surface_t *cairo_surface;
-
-  gint shadow_top;
-
-  gint shadow_max;
-};
-struct _GdkSurfaceImplQuartzClass 
-{
-  GdkSurfaceImplClass parent_class;
-
-  CGContextRef  (* get_context)     (GdkSurfaceImplQuartz *window,
-                                     gboolean             antialias);
-  void          (* release_context) (GdkSurfaceImplQuartz *window,
-                                     CGContextRef         cg_context);
-};
-
-GType _gdk_surface_impl_quartz_get_type (void);
-
-CGContextRef gdk_quartz_surface_get_context     (GdkSurfaceImplQuartz *window,
-                                                gboolean             antialias);
-void         gdk_quartz_surface_release_context (GdkSurfaceImplQuartz *window,
-                                                CGContextRef         context);
-
-/* Root window implementation for Quartz
- */
-
-typedef struct _GdkRootWindowImplQuartz GdkRootWindowImplQuartz;
-typedef struct _GdkRootWindowImplQuartzClass GdkRootWindowImplQuartzClass;
-
-#define GDK_TYPE_ROOT_SURFACE_IMPL_QUARTZ              (_gdk_root_surface_impl_quartz_get_type ())
-#define GDK_ROOT_SURFACE_IMPL_QUARTZ(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_ROOT_SURFACE_IMPL_QUARTZ, GdkRootWindowImplQuartz))
-#define GDK_ROOT_SURFACE_IMPL_QUARTZ_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_ROOT_SURFACE_IMPL_QUARTZ, GdkRootWindowImplQuartzClass))
-#define GDK_IS_ROOT_SURFACE_IMPL_QUARTZ(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_ROOT_SURFACE_IMPL_QUARTZ))
-#define GDK_IS_ROOT_SURFACE_IMPL_QUARTZ_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_ROOT_SURFACE_IMPL_QUARTZ))
-#define GDK_ROOT_SURFACE_IMPL_QUARTZ_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_ROOT_SURFACE_IMPL_QUARTZ, GdkRootWindowImplQuartzClass))
-
-struct _GdkRootWindowImplQuartz
-{
-  GdkSurfaceImplQuartz parent_instance;
-};
-struct _GdkRootWindowImplQuartzClass 
-{
-  GdkSurfaceImplQuartzClass parent_class;
-};
-
-GType _gdk_root_surface_impl_quartz_get_type (void);
-
-GList *get_toplevels (void);
-
-G_END_DECLS
-
-#endif /* __GDK_SURFACE_QUARTZ_H__ */
diff --git a/gdk/quartz/gdkutils-quartz.c b/gdk/quartz/gdkutils-quartz.c
deleted file mode 100644 (file)
index 30eff8a..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-/* gdkutils-quartz.c
- *
- * Copyright (C) 2005 Imendio AB
- * Copyright (C) 2010  Kristian Rietveld  <kris@gtk.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include <AppKit/AppKit.h>
-
-#include <gdkquartzutils.h>
-#include "gdkprivate-quartz.h"
-
-NSImage *
-gdk_quartz_pixbuf_to_ns_image_libgtk_only (GdkPixbuf *pixbuf)
-{
-  NSBitmapImageRep  *bitmap_rep;
-  NSImage           *image;
-  gboolean           has_alpha;
-  
-  has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
-  
-  /* Create a bitmap image rep */
-  bitmap_rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL 
-                                         pixelsWide:gdk_pixbuf_get_width (pixbuf)
-                                        pixelsHigh:gdk_pixbuf_get_height (pixbuf)
-                                        bitsPerSample:8 samplesPerPixel:has_alpha ? 4 : 3
-                                        hasAlpha:has_alpha isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace
-                                        bytesPerRow:0 bitsPerPixel:0];
-       
-  {
-    /* Add pixel data to bitmap rep */
-    guchar *src, *dst;
-    int src_stride, dst_stride;
-    int x, y;
-               
-    src_stride = gdk_pixbuf_get_rowstride (pixbuf);
-    dst_stride = [bitmap_rep bytesPerRow];
-               
-    for (y = 0; y < gdk_pixbuf_get_height (pixbuf); y++) 
-      {
-       src = gdk_pixbuf_get_pixels (pixbuf) + y * src_stride;
-       dst = [bitmap_rep bitmapData] + y * dst_stride;
-       
-       for (x = 0; x < gdk_pixbuf_get_width (pixbuf); x++)
-         {
-           if (has_alpha)
-             {
-               guchar red, green, blue, alpha;
-               
-               red = *src++;
-               green = *src++;
-               blue = *src++;
-               alpha = *src++;
-               
-               *dst++ = (red * alpha) / 255;
-               *dst++ = (green * alpha) / 255;
-               *dst++ = (blue * alpha) / 255;
-               *dst++ = alpha;
-             }
-           else
-            {
-              *dst++ = *src++;
-              *dst++ = *src++;
-              *dst++ = *src++;
-            }
-         }
-      }        
-  }
-       
-  image = [[NSImage alloc] init];
-  [image addRepresentation:bitmap_rep];
-  [bitmap_rep release];
-  [image autorelease];
-       
-  return image;
-}
-
-NSEvent *
-gdk_quartz_event_get_nsevent (GdkEvent *event)
-{
-  /* FIXME: If the event here is unallocated, we crash. */
-  return ((GdkEventPrivate *) event)->windowing_data;
-}
-
-/*
- * Code for key code conversion
- *
- * Copyright (C) 2009 Paul Davis
- */
-gunichar
-gdk_quartz_get_key_equivalent (guint key)
-{
-  if (key >= GDK_KEY_A && key <= GDK_KEY_Z)
-    return key + (GDK_KEY_a - GDK_KEY_A);
-
-  if (key >= GDK_KEY_space && key <= GDK_KEY_asciitilde)
-    return key;
-
-  switch (key)
-    {
-      case GDK_KEY_BackSpace:
-        return NSBackspaceCharacter;
-      case GDK_KEY_Delete:
-        return NSDeleteFunctionKey;
-      case GDK_KEY_Pause:
-        return NSPauseFunctionKey;
-      case GDK_KEY_Scroll_Lock:
-        return NSScrollLockFunctionKey;
-      case GDK_KEY_Sys_Req:
-        return NSSysReqFunctionKey;
-      case GDK_KEY_Home:
-        return NSHomeFunctionKey;
-      case GDK_KEY_Left:
-      case GDK_KEY_leftarrow:
-        return NSLeftArrowFunctionKey;
-      case GDK_KEY_Up:
-      case GDK_KEY_uparrow:
-        return NSUpArrowFunctionKey;
-      case GDK_KEY_Right:
-      case GDK_KEY_rightarrow:
-        return NSRightArrowFunctionKey;
-      case GDK_KEY_Down:
-      case GDK_KEY_downarrow:
-        return NSDownArrowFunctionKey;
-      case GDK_KEY_Page_Up:
-        return NSPageUpFunctionKey;
-      case GDK_KEY_Page_Down:
-        return NSPageDownFunctionKey;
-      case GDK_KEY_End:
-        return NSEndFunctionKey;
-      case GDK_KEY_Begin:
-        return NSBeginFunctionKey;
-      case GDK_KEY_Select:
-        return NSSelectFunctionKey;
-      case GDK_KEY_Print:
-        return NSPrintFunctionKey;
-      case GDK_KEY_Execute:
-        return NSExecuteFunctionKey;
-      case GDK_KEY_Insert:
-        return NSInsertFunctionKey;
-      case GDK_KEY_Undo:
-        return NSUndoFunctionKey;
-      case GDK_KEY_Redo:
-        return NSRedoFunctionKey;
-      case GDK_KEY_Menu:
-        return NSMenuFunctionKey;
-      case GDK_KEY_Find:
-        return NSFindFunctionKey;
-      case GDK_KEY_Help:
-        return NSHelpFunctionKey;
-      case GDK_KEY_Break:
-        return NSBreakFunctionKey;
-      case GDK_KEY_Mode_switch:
-        return NSModeSwitchFunctionKey;
-      case GDK_KEY_F1:
-        return NSF1FunctionKey;
-      case GDK_KEY_F2:
-        return NSF2FunctionKey;
-      case GDK_KEY_F3:
-        return NSF3FunctionKey;
-      case GDK_KEY_F4:
-        return NSF4FunctionKey;
-      case GDK_KEY_F5:
-        return NSF5FunctionKey;
-      case GDK_KEY_F6:
-        return NSF6FunctionKey;
-      case GDK_KEY_F7:
-        return NSF7FunctionKey;
-      case GDK_KEY_F8:
-        return NSF8FunctionKey;
-      case GDK_KEY_F9:
-        return NSF9FunctionKey;
-      case GDK_KEY_F10:
-        return NSF10FunctionKey;
-      case GDK_KEY_F11:
-        return NSF11FunctionKey;
-      case GDK_KEY_F12:
-        return NSF12FunctionKey;
-      case GDK_KEY_F13:
-        return NSF13FunctionKey;
-      case GDK_KEY_F14:
-        return NSF14FunctionKey;
-      case GDK_KEY_F15:
-        return NSF15FunctionKey;
-      case GDK_KEY_F16:
-        return NSF16FunctionKey;
-      case GDK_KEY_F17:
-        return NSF17FunctionKey;
-      case GDK_KEY_F18:
-        return NSF18FunctionKey;
-      case GDK_KEY_F19:
-        return NSF19FunctionKey;
-      case GDK_KEY_F20:
-        return NSF20FunctionKey;
-      case GDK_KEY_F21:
-        return NSF21FunctionKey;
-      case GDK_KEY_F22:
-        return NSF22FunctionKey;
-      case GDK_KEY_F23:
-        return NSF23FunctionKey;
-      case GDK_KEY_F24:
-        return NSF24FunctionKey;
-      case GDK_KEY_F25:
-        return NSF25FunctionKey;
-      case GDK_KEY_F26:
-        return NSF26FunctionKey;
-      case GDK_KEY_F27:
-        return NSF27FunctionKey;
-      case GDK_KEY_F28:
-        return NSF28FunctionKey;
-      case GDK_KEY_F29:
-        return NSF29FunctionKey;
-      case GDK_KEY_F30:
-        return NSF30FunctionKey;
-      case GDK_KEY_F31:
-        return NSF31FunctionKey;
-      case GDK_KEY_F32:
-        return NSF32FunctionKey;
-      case GDK_KEY_F33:
-        return NSF33FunctionKey;
-      case GDK_KEY_F34:
-        return NSF34FunctionKey;
-      case GDK_KEY_F35:
-        return NSF35FunctionKey;
-      default:
-        break;
-    }
-
-  return '\0';
-}
diff --git a/gdk/quartz/meson.build b/gdk/quartz/meson.build
deleted file mode 100644 (file)
index 37c3ef2..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-# FIXME: do we need to do an add_language() for objective-c here?
-gdk_quartz_sources = files([
-  'GdkQuartzView.c',
-  'GdkQuartzNSWindow.c',
-  'gdkcairocontext-quartz.c',
-  'gdkcursor-quartz.c',
-  'gdkdevice-core-quartz.c',
-  'gdkdevicemanager-core-quartz.c',
-  'gdkdisplay-quartz.c',
-  'gdkdisplaymanager-quartz.c',
-  'gdkdnd-quartz.c',
-  'gdkevents-quartz.c',
-  'gdkeventloop-quartz.c',
-  'gdkglcontext-quartz.c',
-  'gdkglobals-quartz.c',
-  'gdkkeys-quartz.c',
-  'gdkscreen-quartz.c',
-  'gdkselection-quartz.c',
-  'gdkutils-quartz.c',
-  'gdksurface-quartz.c',
-])
-
-gdk_quartz_public_headers = files([
-  'gdkquartzcursor.h',
-  'gdkquartzdevice-core.h',
-  'gdkquartzdevicemanager-core.h',
-  'gdkquartzdisplay.h',
-  'gdkquartzdisplaymanager.h',
-  'gdkquartzdnd.h',
-  'gdkquartzkeys.h',
-  'gdkquartzscreen.h',
-  'gdkquartzutils.h',
-  'gdkquartzsurface.h',
-])
-
-install_headers(gdk_quartz_public_headers, 'gdkquartz.h', subdir: 'gtk-4.0/gdk/quartz/')
-
-gdk_quartz_deps = [ # FIXME
-]
-
-libgdk_quartz = static_library('gdk-quartz',
-  gdk_quartz_sources, gdkconfig, gdkenum_h,
-  include_directories: [confinc, gdkinc],
-  c_args: ['-DGTK_COMPILATION', '-DG_LOG_DOMAIN="Gdk"', '-xobjective-c'],
-  dependencies: [gdk_deps, gdk_quartz_deps])
diff --git a/gdk/quartz/xcursors.h b/gdk/quartz/xcursors.h
deleted file mode 100644 (file)
index 60284fd..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-static const struct { gint width, height; gint hotx, hoty; const guchar *bits; } xcursors[] = {
-{ 14, 14, 6, 6, (guchar *) "\x07\xb8\x0f\x3c\x1f\x3e\x3e\x1f\xfc\x0f\xf8\x07\xf0\x03\xf0\x03\xf8\x07\xfc\x0f\x3e\x1f\x1f\x3e\x0f\x3c\x07\x38" },
-{ 16, 16, 7, 7, (guchar *) "\x0f\xf0\x1f\xf8\x3f\xfc\x7f\xfe\xfe\x7f\xfc\x3f\xf8\x1f\xf0\x0f\xf0\x0f\xf8\x1f\xfc\x3f\xfe\x7f\x7f\xfe\x3f\xfc\x1f\xf8\x0f\xf0" },
-{ 14, 14, 13, 0, (guchar *) "\x00\xb0\x00\x3c\x00\x1f\xc0\x1f\xf0\x0f\xfc\x0f\xc0\x07\xe0\x07\x70\x03\x38\x03\x1c\x01\x0e\x01\x07\x00\x02\x00" },
-{ 16, 16, 14, 1, (guchar *) "\x00\xe0\x00\xf8\x00\xfe\x80\x7f\xe0\x7f\xf8\x3f\xfc\x3f\xfc\x1f\xe0\x1f\xf0\x0f\xf8\x0f\x7c\x07\x3e\x07\x1f\x02\x0e\x00\x04\x00" },
-{ 8, 10, 3, 9, (guchar *) "\xff\x00\xff\x18\x18\x18\x18\x5a\x3c\x18" },
-{ 10, 12, 4, 10, (guchar *) "\xff\x23\xff\x03\xff\x03\xff\x03\xff\x03\x78\x00\x78\x00\xfe\x01\xfe\x01\xfe\x01\xfc\x00\x78\x00" },
-{ 8, 10, 3, 9, (guchar *) "\x18\x3c\x5a\x18\x18\x18\x18\xff\x00\xff" },
-{ 10, 12, 4, 10, (guchar *) "\x30\x20\x78\x00\xfe\x01\xfe\x01\xfe\x01\x78\x00\x78\x00\xff\x03\xff\x03\xff\x03\xff\x03\xff\x03" },
-{ 16, 8, 14, 3, (guchar *) "\x80\x00\xe0\x03\x11\x06\xff\xff\x00\x18\x00\x04\x00\x02\xff\x03" },
-{ 16, 9, 14, 4, (guchar *) "\xe0\x00\xf0\x03\xf9\x07\xff\xff\xff\xff\xff\xff\xff\x1f\xff\x07\xff\x03" },
-{ 13, 14, 6, 6, (guchar *) "\x47\x9c\x44\x04\x44\x04\x44\x04\xff\x1f\x45\x14\x45\x14\x45\x14\x45\x14\xff\x1f\x44\x04\x44\x04\x44\x04\x47\x1c" },
-{ 15, 16, 7, 7, (guchar *) "\xdf\x7d\xdf\x7d\xdf\x7d\xdc\x1d\xff\x7f\xff\x7f\xff\x7f\xdf\x7d\xdf\x7d\xff\x7f\xff\x7f\xff\x7f\xdc\x1d\xdf\x7d\xdf\x7d\xdf\x7d" },
-{ 14, 14, 0, 13, (guchar *) "\x03\x80\x03\x00\x23\x08\x23\x04\x23\x02\x23\x01\xa3\x00\x63\x00\xe3\x0f\x03\x00\x03\x00\x03\x00\xff\x3f\xff\x3f" },
-{ 16, 16, 1, 14, (guchar *) "\x0f\x00\x0f\x00\xef\x30\xef\x38\xef\x1c\xef\x0e\xef\x07\xef\x03\xef\x3f\xef\x3f\xef\x3f\x0f\x00\xff\xff\xff\xff\xff\xff\xff\xff" },
-{ 14, 14, 13, 13, (guchar *) "\x00\xb0\x00\x30\x04\x31\x08\x31\x10\x31\x20\x31\x40\x31\x80\x31\xfc\x31\x00\x30\x00\x30\x00\x30\xff\x3f\xff\x3f" },
-{ 16, 16, 14, 14, (guchar *) "\x00\xf0\x00\xf0\x0c\xf7\x1c\xf7\x38\xf7\x70\xf7\xe0\xf7\xc0\xf7\xfc\xf7\xfc\xf7\xfc\xf7\x00\xf0\xff\xff\xff\xff\xff\xff\xff\xff" },
-{ 13, 14, 6, 13, (guchar *) "\x40\x80\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00\x44\x04\x48\x02\x50\x01\xe0\x00\x40\x00\x00\x00\xff\x1f\xff\x1f" },
-{ 15, 16, 7, 14, (guchar *) "\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xcc\x19\xdc\x1d\xf8\x0f\xf0\x07\xe0\x03\xc0\x01\xff\x7f\xff\x7f\xff\x7f\xff\x7f" },
-{ 14, 10, 7, 9, (guchar *) "\xc0\x80\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xff\x3f\xff\x3f" },
-{ 16, 12, 8, 10, (guchar *) "\xc0\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x03\xff\xff\xff\xff\xff\xff\xff\xff" },
-{ 15, 16, 8, 8, (guchar *) "\xff\xff\x01\x00\xfd\x7f\x05\x40\xf5\x5f\x15\x50\xd5\x57\x55\x54\x55\x55\xd5\x55\x15\x54\xf5\x57\x05\x50\xfd\x5f\x01\x40\xff\x7f" },
-{ 16, 16, 8, 8, (guchar *) "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" },
-{ 10, 14, 4, 0, (guchar *) "\x30\x90\x30\x00\x78\x00\x78\x00\xfc\x00\xfc\x00\xfe\x01\xfe\x01\x33\x03\x31\x02\x30\x00\x30\x00\x30\x00\x30\x00" },
-{ 12, 16, 5, 1, (guchar *) "\xf0\x20\xf0\x00\xf8\x01\xf8\x01\xfc\x03\xfc\x03\xfe\x07\xfe\x07\xff\x0f\xff\x0f\xff\x0f\xf7\x0e\xf0\x00\xf0\x00\xf0\x00\xf0\x00" },
-{ 14, 14, 7, 7, (guchar *) "\xe0\x81\xf8\x07\xfc\x0f\x1e\x1e\x0e\x1c\x07\x38\x07\x38\x07\x38\x07\x38\x0e\x1c\x1e\x1e\xfc\x0f\xf8\x07\xe0\x01" },
-{ 16, 16, 8, 8, (guchar *) "\xe0\x07\xf8\x1f\xfc\x3f\xfe\x7f\xfe\x7f\x3f\xfc\x1f\xf8\x1f\xf8\x1f\xf8\x1f\xf8\x3f\xfc\xfe\x7f\xfe\x7f\xfc\x3f\xf8\x1f\xe0\x07" },
-{ 14, 16, 6, 3, (guchar *) "\xfc\x8f\xe6\x19\x13\x33\xc9\x24\x79\x24\x11\x22\xe3\x31\xfe\x1f\xca\x14\xca\x14\xca\x14\xea\x15\xcb\x34\x0f\x3c\xff\x3f\xff\x3f" },
-{ 15, 16, 6, 3, (guchar *) "\xfe\x1f\xf7\x39\xdb\x77\xed\x6d\xfd\x6f\xf9\x66\xf3\x73\xff\x3f\xeb\x35\xeb\x35\xeb\x35\xfb\x37\xeb\x75\xcf\x7c\xff\x7f\xff\x7f" },
-{ 15, 16, 7, 9, (guchar *) "\xf8\x8f\x04\x10\x06\x60\x0a\x58\xf2\x47\x03\x40\x03\x40\x02\x40\x02\x40\x9a\x58\x56\x55\xd7\x55\x5b\x59\x02\x40\x02\x40\xfc\x3f" },
-{ 16, 16, 7, 9, (guchar *) "\xf8\x0f\xfc\x1f\xfe\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xfc\x3f" },
-{ 16, 15, 7, 7, (guchar *) "\x40\x01\x40\x01\x40\x01\x40\x01\x40\x01\x40\x01\x7f\xff\x00\x00\x7f\xff\x40\x01\x40\x01\x40\x01\x40\x01\x40\x01\x40\x01" },
-{ 16, 16, 7, 7, (guchar *) "\xe0\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x03\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x03" },
-{ 16, 15, 7, 7, (guchar *) "\x42\x21\x45\x51\x4a\x29\x54\x15\x68\x0b\x50\x05\xbf\xfe\x40\x01\xbf\xfe\x50\x05\x68\x0b\x54\x15\x4a\x29\x45\x51\x42\x21" },
-{ 16, 15, 7, 7, (guchar *) "\x66\x33\x6d\xdb\x7b\x6f\x76\x37\x6c\x1b\x5f\xfd\x3f\xfe\x80\x00\x3f\xfe\x5f\xfd\x6c\x1b\x76\x37\x7b\x6f\x6d\xdb\x66\x33" },
-{ 16, 15, 7, 7, (guchar *) "\x80\x00\x80\x00\x80\x00\x80\x00\x80\x00\x80\x00\x80\x00\x7f\xff\x80\x00\x80\x00\x80\x00\x80\x00\x80\x00\x80\x00\x80\x00" },
-{ 16, 16, 7, 7, (guchar *) "\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xff\xff\xff\xff\xff\xff\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01" },
-{ 15, 15, 7, 7, (guchar *) "\x40\x81\x60\x03\x50\x05\x48\x09\x44\x11\x42\x21\x7f\x7f\x00\x00\x7f\x7f\x42\x21\x44\x11\x48\x09\x50\x05\x60\x03\x40\x01" },
-{ 16, 16, 7, 7, (guchar *) "\xe0\x03\xf0\x07\xf8\x0f\xdc\x1d\xce\x39\xc7\x71\xff\xff\x7f\xff\xff\xff\xc7\x71\xce\x39\xdc\x1d\xf8\x0f\xf0\x07\xe0\x03\xc0\x01" },
-{ 10, 10, 5, 5, (guchar *) "\x78\x90\xfe\x01\xfe\x01\xff\x03\xff\x03\xff\x03\xff\x03\xfe\x01\xfe\x01\x78\x00" },
-{ 12, 12, 6, 6, (guchar *) "\xf8\x21\xfe\x07\xfe\x07\xff\x0f\xff\x0f\xff\x0f\xff\x0f\xff\x0f\xff\x0f\xfe\x07\xfe\x07\xf8\x01" },
-{ 12, 12, 6, 5, (guchar *) "\xff\x9f\x01\x08\x01\x08\x01\x08\x01\x08\x61\x08\x61\x08\x01\x08\x01\x08\x01\x08\x01\x08\xff\x0f" },
-{ 14, 14, 7, 6, (guchar *) "\xff\x3f\xff\x3f\xff\x3f\x07\x38\x07\x38\xe7\x39\xe7\x39\xe7\x39\xe7\x39\x07\x38\x07\x38\xff\x3f\xff\x3f\xff\x3f" },
-{ 10, 14, 5, 7, (guchar *) "\x30\x90\x78\x00\xfc\x00\xb6\x01\x33\x03\x30\x00\x30\x00\x30\x00\x30\x00\x33\x03\xb6\x01\xfc\x00\x78\x00\x30\x00" },
-{ 12, 16, 6, 8, (guchar *) "\xf0\x20\xf8\x01\xfc\x03\xfe\x07\xff\x0f\xff\x0f\xff\x0f\xf0\x00\xf0\x00\xff\x0f\xff\x0f\xff\x0f\xfe\x07\xfc\x03\xf8\x01\xf0\x00" },
-{ 15, 15, 14, 0, (guchar *) "\x00\xc0\x00\x30\x00\x3c\x00\x1f\xc0\x1f\xf0\x0f\xfc\x0f\x80\x07\x40\x07\x20\x03\x10\x03\x08\x01\x04\x01\x02\x00\x01\x00" },
-{ 15, 16, 14, 0, (guchar *) "\x00\x60\x00\x78\x00\x7e\x80\x3f\xe0\x1f\xf8\x1f\xfe\x0f\xfe\x0f\xe0\x07\xf0\x07\xb8\x03\x9c\x03\x8e\x01\x87\x01\x03\x00\x01\x00" },
-{ 15, 15, 14, 0, (guchar *) "\x00\x40\x00\x30\x00\x3c\x00\x1f\xc0\x1f\x00\x0e\x00\x0d\x80\x04\x40\x04\x20\x00\x10\x00\x08\x00\x04\x00\x02\x00\x01\x00" },
-{ 15, 15, 14, 0, (guchar *) "\x00\x60\x00\x78\x00\x3e\x80\x3f\xe0\x1f\xe0\x1f\x80\x0f\xc0\x0f\xe0\x06\x70\x02\x38\x00\x1c\x00\x0e\x00\x07\x00\x03\x00" },
-{ 12, 12, 6, 5, (guchar *) "\xff\x1f\x91\x08\x99\x09\x0d\x0b\x07\x0e\x61\x08\x61\x08\x07\x0e\x0d\x0b\x99\x09\x91\x08\xff\x0f" },
-{ 14, 14, 7, 6, (guchar *) "\xff\x3f\xff\x3f\xf3\x33\xfb\x37\x3f\x3f\xdf\x3e\xef\x3d\xef\x3d\xdf\x3e\x3f\x3f\xfb\x37\xf3\x33\xff\x3f\xff\x3f" },
-{ 14, 14, 6, 6, (guchar *) "\xf1\x03\xfb\x07\x1f\x0c\x09\x08\x19\x00\x3f\x00\x00\x00\x00\x00\x00\x3f\x00\x26\x04\x24\x0c\x3e\xf8\x37\xf0\x23" },
-{ 16, 16, 7, 7, (guchar *) "\xe3\x07\xf7\x0f\xff\x1f\xff\x3f\x3f\x38\xff\x30\xff\x00\xff\x00\x00\xff\x00\xff\x0c\xfe\x1c\xfc\xfc\xff\xf8\xff\xf0\xef\xe0\xc7" },
-{ 14, 14, 7, 7, (guchar *) "\xc0\x00\xe0\x01\xf0\x03\xc0\x00\xc4\x08\xc6\x18\xff\x3f\xff\x3f\xc6\x18\xc4\x08\xc0\x00\xf0\x03\xe0\x01\xc0\x00" },
-{ 16, 16, 8, 8, (guchar *) "\xc0\x03\xc0\x07\xe0\x07\xf0\x0f\xe8\x17\xdc\x3b\xff\xff\xff\xff\xff\xff\xff\xff\xdc\x3b\xe8\x17\xf0\x0f\xe0\x07\xc0\x03\xc0\x03" },
-{ 16, 15, 14, 2, (guchar *) "\x00\x1e\x00\x0e\x01\xcc\xf9\x0d\xff\x0f\x7f\x0c\x3f\x0c\x06\x1c\x00\x0f\xf8\x07\x10\x00\x10\x00\x10\x00\x10\x00\x78\x00" },
-{ 16, 16, 14, 3, (guchar *) "\x00\x3f\x00\x3f\x03\xff\xff\xff\xff\xff\xff\x3f\xff\x3f\xff\x3f\xff\x3f\xff\x3f\xfe\x1f\xf8\x0f\x38\x00\x38\x00\xfc\x00\xfc\x00" },
-{ 16, 16, 2, 0, (guchar *) "\xfc\x00\x08\x01\x13\x02\x57\x05\x13\x04\xd3\x05\x1f\x3c\x1c\xfc\x10\xe4\x10\xe4\x90\xf4\x90\xe4\x90\x04\x88\x08\x84\x10\x7c\x1f" },
-{ 16, 16, 2, 0, (guchar *) "\xfc\x00\xfb\x01\xf7\x03\xff\x07\xf7\x07\xf7\x3f\xff\x7f\xff\xff\xfc\xf7\xf0\xf7\xf0\xff\xf0\xf7\xf0\xe7\xf8\x0f\xfc\x1f\x7c\x1f" },
-{ 13, 16, 12, 0, (guchar *) "\x00\x18\x00\x1e\x80\x07\xc0\x03\xe0\x01\xf0\x03\xf8\x07\xfa\x03\xff\x07\xfd\x07\xf0\x03\xf0\x01\x29\x00\x23\x00\x16\x00\x0c\x00" },
-{ 13, 16, 12, 0, (guchar *) "\x00\xdc\x00\x1f\xc0\x0f\xe0\x07\xf0\x03\xf8\x07\xfe\x0f\xff\x0f\xff\x0f\xff\x0f\xff\x07\xff\x03\xff\x01\x7f\x00\x3f\x00\x1e\x00" },
-{ 15, 14, 0, 0, (guchar *) "\xfe\x01\x01\x02\x7e\x04\x08\x08\x70\x08\x08\x08\x70\x14\x08\x22\x30\x41\xc0\x20\x40\x12\x80\x08\x00\x05\x00\x02" },
-{ 16, 16, 0, 1, (guchar *) "\xfe\x01\xff\x03\xff\x07\xff\x0f\xfe\x1f\xf8\x1f\xfc\x1f\xf8\x3f\xfc\x7f\xf8\xff\xf0\x7f\xe0\x3f\xc0\x1f\x80\x0f\x00\x07\x00\x02" },
-{ 15, 14, 6, 8, (guchar *) "\x7c\x1f\xc6\x31\x83\x60\x01\x40\x01\x40\x01\x40\x01\x40\x03\x60\x06\x30\x0c\x18\x18\x0c\x30\x06\x60\x03\xc0\x01" },
-{ 15, 14, 6, 8, (guchar *) "\x7c\x9f\xfe\x3f\xc7\x71\x83\x60\x03\x60\x03\x60\x43\x61\x87\x70\x0e\x38\x1c\x1c\x38\x0e\xf0\x07\xe0\x03\xc0\x01" },
-{ 16, 16, 8, 8, (guchar *) "\xff\xff\xab\xaa\x55\xd5\xab\xaa\x05\xd0\x0b\xa0\x05\xd0\x0b\xa0\x05\xd0\x0b\xa0\x05\xd0\x0b\xa0\x55\xd5\xab\xaa\x55\xd5\xff\xff" },
-{ 16, 16, 8, 8, (guchar *) "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" },
-{ 14, 14, 7, 6, (guchar *) "\xfe\x1f\xfc\x0f\xf9\x27\xf3\x33\xe7\x39\xcf\x3c\xff\x3f\xff\x3f\xcf\x3c\xe7\x39\xf3\x33\xf9\x27\xfc\x0f\xfe\x1f" },
-{ 16, 16, 8, 7, (guchar *) "\xfc\x3f\xfe\x7f\xfe\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x7f\xfe\x7f\xfc\x3f" },
-{ 8, 14, 0, 0, (guchar *) "\x01\x03\x07\x0f\x1f\x3f\x7f\xff\x1f\x1b\x31\x30\x60\x60" },
-{ 10, 16, 1, 1, (guchar *) "\x03\xc0\x07\x00\x0f\x00\x1f\x00\x3f\x00\x7f\x00\xff\x00\xff\x01\xff\x03\xff\x03\x7f\x00\xf7\x00\xf3\x00\xe0\x01\xe0\x01\xc0\x00" },
-{ 14, 13, 0, 6, (guchar *) "\x03\x00\x03\x00\x83\x00\x43\x00\x23\x00\x13\x00\xfb\x3f\x13\x00\x23\x00\x43\x00\x83\x00\x03\x00\x03\x00" },
-{ 16, 15, 1, 7, (guchar *) "\x0f\x00\x0f\x00\x0f\x03\x8f\x03\xcf\x01\xef\x00\xff\xff\xff\xff\xff\xff\xef\x00\xcf\x01\x8f\x03\x0f\x03\x0f\x00\x0f\x00" },
-{ 10, 14, 0, 7, (guchar *) "\x03\x10\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\xff\x03\xff\x03\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00" },
-{ 12, 16, 1, 8, (guchar *) "\x0f\xc0\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\xff\x0f\xff\x0f\xff\x0f\xff\x0f\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00" },
-{ 16, 16, 8, 8, (guchar *) "\x01\xc0\xfe\xbf\xfe\xbf\x22\xa2\xa2\xaa\xa2\xaa\xa2\xaa\xa2\xaa\x22\xa2\xfe\xbf\xfe\xbf\xfe\xbf\xfe\xbf\xfe\xbf\xfe\xbf\x01\xc0" },
-{ 15, 16, 8, 8, (guchar *) "\xfe\xbf\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xfe\x3f" },
-{ 10, 10, 0, 9, (guchar *) "\x03\x10\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\xff\x03\xff\x03" },
-{ 12, 12, 1, 10, (guchar *) "\x0f\xc0\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\xff\x0f\xff\x0f\xff\x0f\xff\x0f" },
-{ 10, 10, 9, 9, (guchar *) "\x00\x13\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\xff\x03\xff\x03" },
-{ 12, 12, 10, 10, (guchar *) "\x00\xcf\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\xff\x0f\xff\x0f\xff\x0f\xff\x0f" },
-{ 16, 16, 14, 5, (guchar *) "\xc0\x01\x78\x0f\x40\x01\x81\x00\xc2\xe1\x24\xd2\xb8\x0e\xa0\x02\x20\x02\x40\x01\x20\x02\x90\x04\x48\x09\x28\x0a\x1e\x3c\x1f\xfc" },
-{ 16, 16, 14, 5, (guchar *) "\xf8\x07\xfc\x0f\xfc\x1f\xc3\x41\xe7\xe3\xfe\xff\xfc\xdf\xf8\x0f\xe0\x07\xe0\x03\xf0\x07\xf8\x0f\xfc\x1f\x7e\x3f\x3f\xfe\x3f\xfe" },
-{ 16, 16, 8, 8, (guchar *) "\x01\xc0\xfe\xbf\xfe\xbf\x22\xa2\x2a\xaa\x2a\xaa\x2a\xaa\x2a\xaa\x22\xa2\xfe\xbf\xfe\xbf\xfe\xbf\xfe\xbf\xfe\xbf\xfe\xbf\x01\xc0" },
-{ 15, 16, 8, 8, (guchar *) "\xfe\xbf\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xfe\x3f" },
-{ 15, 14, 4, 1, (guchar *) "\xe0\x00\x30\x00\x60\x00\xc0\x00\xfe\x1f\x01\x20\xcd\x6c\xcd\x6c\xcd\x6c\x01\x60\x01\x60\x06\x38\x18\x06\xe0\x01" },
-{ 16, 16, 4, 1, (guchar *) "\xf0\x01\x78\x00\xf0\x00\xe0\x00\xfe\x1f\xff\x3f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\xef\xf8\x07\xf0\x03\xe0\x01" },
-{ 11, 16, 10, 15, (guchar *) "\x0e\x10\x11\x00\x31\x00\x52\x00\x5e\x00\x84\x00\x88\x00\x08\x01\x10\x01\x30\x02\x20\x02\x40\x04\x80\x07\x00\x07\x00\x06\x00\x04" },
-{ 13, 16, 11, 15, (guchar *) "\x3f\xc0\x7f\x00\xff\x00\xfe\x00\xfc\x01\xfc\x01\xf8\x03\xf0\x03\xf0\x07\xe0\x07\xe0\x0f\xc0\x1f\x80\x1f\x00\x1f\x00\x1e\x00\x1c" },
-{ 15, 16, 7, 12, (guchar *) "\xe0\x01\xf0\x03\xf8\x07\xcc\x0c\xcc\x0c\xf8\x07\xf0\x03\xe0\x01\xe1\x21\xe1\x61\xc2\x10\x1c\x0e\xe0\x01\xf8\x47\x0f\x7c\x01\x20" },
-{ 16, 16, 7, 12, (guchar *) "\xf0\x03\xf8\x07\xfc\x0f\xfe\x1f\xfe\x1f\xfc\x0f\xf8\x07\xf1\x83\xf1\xe3\xf3\xf3\xef\x39\x1e\x1e\xe0\x01\xfe\xc7\xff\xff\x0f\x7c" },
-{ 10, 10, 4, 5, (guchar *) "\x30\x10\x30\x00\x30\x00\x30\x00\xff\x03\xff\x03\x30\x00\x30\x00\x30\x00\x30\x00" },
-{ 12, 12, 5, 6, (guchar *) "\xf0\xc0\xf0\x00\xf0\x00\xf0\x00\xff\x0f\xff\x0f\xff\x0f\xff\x0f\xf0\x00\xf0\x00\xf0\x00\xf0\x00" },
-{ 9, 15, 4, 7, (guchar *) "\x7c\x10\xfe\x00\xc7\x01\x83\x01\x87\x01\xc6\x01\xe0\x00\x78\x00\x38\x00\x28\x00\x28\x00\xee\x00\x6c\x00\x38\x00\x10\x00" },
-{ 11, 16, 5, 8, (guchar *) "\xf8\xc0\xfc\x01\xfe\x03\xff\x07\x8f\x07\x9f\x07\xde\x07\xfc\x03\xf8\x01\xf8\x00\xf8\x00\xfc\x01\xfe\x03\xfc\x01\xf8\x00\x70\x00" },
-{ 8, 14, 7, 0, (guchar *) "\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff\xf8\xd8\x8c\x0c\x06\x06" },
-{ 10, 16, 8, 1, (guchar *) "\x00\xc3\x80\x03\xc0\x03\xe0\x03\xf0\x03\xf8\x03\xfc\x03\xfe\x03\xff\x03\xff\x03\xf8\x03\xbc\x03\x3c\x03\x1e\x00\x1e\x00\x0c\x00" },
-{ 14, 13, 13, 6, (guchar *) "\x00\x30\x00\x30\x40\x30\x80\x30\x00\x31\x00\x32\xff\x37\x00\x32\x00\x31\x80\x30\x40\x30\x00\x30\x00\x30" },
-{ 16, 15, 14, 7, (guchar *) "\x00\xf0\x00\xf0\xc0\xf0\xc0\xf1\x80\xf3\x00\xf7\xff\xff\xff\xff\xff\xff\x00\xf7\x80\xf3\xc0\xf1\xc0\xf0\x00\xf0\x00\xf0" },
-{ 10, 14, 9, 7, (guchar *) "\x00\x13\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\xff\x03\xff\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03" },
-{ 12, 16, 10, 8, (guchar *) "\x00\xcf\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\xff\x0f\xff\x0f\xff\x0f\xff\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f" },
-{ 16, 16, 8, 8, (guchar *) "\x01\xc0\xfe\xbf\xfe\xbf\x22\xa2\xaa\xa2\xaa\xa2\xaa\xa2\xaa\xa2\x22\xa2\xfe\xbf\xfe\xbf\xfe\xbf\xfe\xbf\xfe\xbf\xfe\xbf\x01\xc0" },
-{ 15, 16, 8, 8, (guchar *) "\xfe\xbf\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xfe\x3f" },
-{ 14, 14, 6, 6, (guchar *) "\xff\x3f\x01\x22\x01\x22\x01\x22\xff\x23\x11\x22\x11\x22\x11\x22\x11\x22\xf1\x3f\x11\x20\x11\x20\x11\x20\xff\x3f" },
-{ 16, 16, 7, 7, (guchar *) "\xff\xff\xff\xff\xff\xff\x07\xee\xff\xef\xff\xef\xff\xef\x77\xee\x77\xee\xf7\xff\xf7\xff\xf7\xff\x77\xe0\xff\xff\xff\xff\xff\xff" },
-{ 12, 13, 6, -1, (guchar *) "\x80\x10\x80\x00\xa0\x01\xa0\x01\xb0\x01\xb0\x03\xb8\x03\xb8\x03\xbc\x07\xbc\x07\xbe\x07\xbe\x0f\x1f\x07" },
-{ 16, 16, 8, 0, (guchar *) "\x00\x03\x00\x07\x80\x07\xc0\x0f\xc0\x0f\xe0\x0f\xe0\x1f\xf0\x1f\xf0\x1f\xf8\x3f\xf8\x3f\xfc\x3f\xfc\xff\xfe\xff\xff\x1f\xfe\x07" },
-{ 7, 15, 3, 15, (guchar *) "\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x7f\x3e\x1c\x08" },
-{ 9, 16, 4, 15, (guchar *) "\x7c\xc0\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\xff\x01\xff\x01\xfe\x00\x7c\x00\x38\x00\x10\x00" },
-{ 15, 7, 7, 3, (guchar *) "\x08\x08\x0c\x18\xfe\x3f\x0f\x78\xfe\x3f\x0c\x18\x08\x08" },
-{ 15, 9, 7, 4, (guchar *) "\x18\x8c\x1c\x1c\xfe\x3f\xff\x7f\xff\x7f\xff\x7f\xfe\x3f\x1c\x1c\x18\x0c" },
-{ 15, 7, -1, 3, (guchar *) "\x08\x00\x0c\x00\xfe\x7f\x0f\x00\xfe\x7f\x0c\x00\x08\x00" },
-{ 16, 9, 0, 4, (guchar *) "\x30\x00\x38\x00\xfc\xff\xfe\xff\xff\xff\xfe\xff\xfc\xff\x38\x00\x30\x00" },
-{ 15, 7, 15, 3, (guchar *) "\x00\x08\x00\x18\xff\x3f\x00\x78\xff\x3f\x00\x18\x00\x08" },
-{ 16, 9, 15, 4, (guchar *) "\x00\x0c\x00\x1c\xff\x3f\xff\x7f\xff\xff\xff\x7f\xff\x3f\x00\x1c\x00\x0c" },
-{ 7, 15, 3, -1, (guchar *) "\x08\x9c\x3e\x7f\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14" },
-{ 9, 16, 4, 0, (guchar *) "\x10\xc0\x38\x00\x7c\x00\xfe\x00\xff\x01\xff\x01\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00" },
-{ 7, 15, 3, 7, (guchar *) "\x08\x9c\x3e\x7f\x14\x14\x14\x14\x14\x14\x14\x7f\x3e\x1c\x08" },
-{ 9, 15, 4, 7, (guchar *) "\x38\xc0\x7c\x00\xfe\x00\xff\x01\xff\x01\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\xff\x01\xff\x01\xfe\x00\x7c\x00\x38\x00" },
-{ 15, 16, 10, 0, (guchar *) "\x00\x84\x00\x0e\x00\x1f\x80\x7b\xa0\x7b\x90\x7b\x88\x7b\x88\x7b\x88\x7b\x88\x7b\x8c\x7b\x8e\x7b\xbf\x7b\x18\x11\x00\x1e\x00\x0c" },
-{ 16, 16, 11, 0, (guchar *) "\x00\x1c\x00\x3e\x00\x7f\x00\xff\x60\xff\x70\xff\x78\xff\x78\xff\x78\xff\x78\xff\x7c\xff\x7e\xff\x7f\xff\x7e\x7f\x30\x7e\x00\x3c" },
-{ 14, 14, 7, 7, (guchar *) "\xff\xc0\x01\x00\x01\x00\x01\x00\xf1\x03\x11\x02\x11\x22\x11\x22\x10\x22\xf0\x23\x00\x24\x00\x28\x00\x30\xc0\x3f" },
-{ 16, 16, 8, 8, (guchar *) "\xff\x03\xff\x03\xff\x03\x07\x00\xf7\x0f\xf7\x0f\xf7\xef\x77\xee\x77\xee\xf7\xef\xf0\xef\xf0\xff\x00\xf8\xc0\xff\xc0\xff\xc0\xff" },
-{ 16, 16, 6, 7, (guchar *) "\x04\x08\x08\x04\x08\x04\x10\x02\x10\x02\xe1\xe1\xe6\x19\xf8\x07\xf8\x07\xe6\x19\xe1\xe1\x10\x02\x10\x02\x08\x04\x08\x04\x04\x08" },
-{ 16, 16, 6, 7, (guchar *) "\x06\x18\x0c\x0c\x08\x04\x18\x06\xf1\x83\xf3\xf3\xf6\x3b\xfc\x0f\xfc\x07\xf6\x1f\xf3\xf3\xf1\x83\x18\x02\x18\x06\x0c\x0c\x06\x18" },
-{ 11, 16, 9, 2, (guchar *) "\x00\xe6\x80\x00\x2c\x06\x9e\x00\x16\x06\x3f\x00\x21\x00\x27\x00\x25\x00\x27\x00\x25\x00\x27\x00\x27\x00\x21\x00\x21\x00\x3f\x00" },
-{ 12, 16, 10, 2, (guchar *) "\x00\x4c\x18\x0d\x7c\x0d\x7c\x0d\x7e\x0d\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00" },
-{ 15, 16, 7, 7, (guchar *) "\x80\x80\x40\x01\x40\x01\x40\x01\x20\x02\x20\x02\x20\x02\x9c\x1c\x03\x60\x1c\x1c\x90\x04\x48\x09\x24\x12\x14\x14\x0c\x18\x04\x10" },
-{ 16, 16, 7, 7, (guchar *) "\x80\x00\xc0\x01\xc0\x01\x60\x03\x60\x03\x30\x06\x38\x1e\x9f\x7c\x03\xe0\x1f\x7c\x9c\x1c\xcc\x19\x66\x33\x36\x36\x1e\x3c\x0e\x38" },
-{ 15, 13, 7, 6, (guchar *) "\xc0\x81\xf0\x07\x38\x0e\x0c\x18\x06\x30\x83\x60\x43\x61\x83\x60\x06\x30\x0c\x18\x38\x0e\xf0\x07\xc0\x01" },
-{ 16, 14, 7, 7, (guchar *) "\xe0\x03\xf0\x07\xf8\x0f\x3c\x1e\x0e\x38\x87\x70\xc3\xe1\x63\xe3\xc3\xe1\x87\x70\x0e\x38\x3c\x1e\xf8\x0f\xe0\x03" },
-{ 13, 13, 6, 6, (guchar *) "\x40\xe0\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00\xff\x1f\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00" },
-{ 15, 15, 7, 7, (guchar *) "\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xff\x7f\xff\x7f\xff\x7f\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01" },
-{ 14, 14, 0, 0, (guchar *) "\x03\xc0\x0f\x00\x3e\x00\xfe\x00\xfc\x03\xfc\x0f\xf8\x00\xf8\x00\x30\x01\x30\x02\x20\x04\x20\x08\x00\x10\x00\x20" },
-{ 16, 16, 1, 1, (guchar *) "\x07\x00\x1f\x00\x7f\x00\xfe\x01\xfe\x07\xfc\x3f\xfc\x3f\xf8\x3f\xf8\x03\xf0\x07\xf0\x0e\xe0\x1c\xe0\x38\xe0\x70\x00\xe0\x00\xc0" },
-{ 14, 14, 0, 0, (guchar *) "\xff\xff\xff\x3f\x03\x00\x03\x00\x03\x00\xe3\x0f\x63\x00\xa3\x00\x23\x01\x23\x02\x23\x04\x23\x08\x03\x00\x03\x00" },
-{ 16, 16, 1, 1, (guchar *) "\xff\xff\xff\xff\xff\xff\xff\xff\x0f\x00\xef\x3f\xef\x3f\xef\x3f\xef\x03\xef\x07\xef\x0e\xef\x1c\xef\x38\xef\x30\x0f\x00\x0f\x00" },
-{ 14, 14, 13, 0, (guchar *) "\xff\xff\xff\x3f\x00\x30\x00\x30\x00\x30\xfc\x31\x80\x31\x40\x31\x20\x31\x10\x31\x08\x31\x04\x31\x00\x30\x00\x30" },
-{ 16, 16, 14, 1, (guchar *) "\xff\xff\xff\xff\xff\xff\xff\xff\x00\xf0\xfc\xf7\xfc\xf7\xfc\xf7\xc0\xf7\xe0\xf7\x70\xf7\x38\xf7\x1c\xf7\x0c\xf7\x00\xf0\x00\xf0" },
-{ 13, 14, 6, 0, (guchar *) "\xff\xff\xff\x1f\x00\x00\x40\x00\xe0\x00\x50\x01\x48\x02\x44\x04\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00" },
-{ 15, 16, 7, 1, (guchar *) "\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xc0\x01\xe0\x03\xf0\x07\xf8\x0f\xdc\x1d\xcc\x19\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01" },
-{ 14, 10, 7, 0, (guchar *) "\xff\xff\xff\x3f\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00" },
-{ 16, 12, 8, 1, (guchar *) "\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x03" },
-{ 7, 16, 3, 0, (guchar *) "\x88\x80\x1c\x3e\x7f\x77\x7f\x3e\x1c\x08\x5d\x6b\x49\x41\x41\x41" },
-{ 9, 16, 4, 0, (guchar *) "\x38\x40\x38\x00\x7c\x00\xfe\x00\xff\x01\xff\x01\xff\x01\xfe\x00\x7c\x00\xba\x00\xff\x01\xff\x01\xff\x01\xd7\x01\xd7\x01\xc7\x01" },
-{ 10, 10, 0, 0, (guchar *) "\xff\xe3\xff\x03\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00" },
-{ 12, 12, 1, 1, (guchar *) "\xff\x4f\xff\x0f\xff\x0f\xff\x0f\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00" },
-{ 14, 14, 7, 2, (guchar *) "\x88\xc4\x20\x0a\xc9\x32\xf2\x09\x4c\x06\x43\x18\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00\x40\x01\x40\x01\x80\x00" },
-{ 16, 16, 8, 2, (guchar *) "\xe8\x76\xfb\xdf\xfd\x3f\xfe\xff\xff\x3f\xff\xff\xcf\x79\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x07\xc0\x07\xc0\x07\xc0\x07\x80\x03" },
-{ 10, 10, 9, 0, (guchar *) "\xff\xe3\xff\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03" },
-{ 12, 12, 10, 1, (guchar *) "\xff\x4f\xff\x0f\xff\x0f\xff\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f" },
-{ 16, 16, 15, 9, (guchar *) "\xf8\x07\xf8\x07\xf8\x07\xfc\x0f\x86\x18\x83\x30\x81\xe0\xc1\xe1\xc1\xe1\x21\xe0\x13\x30\x06\x18\xfc\x0f\xf8\x07\xf8\x07\xf8\x07" },
-{ 16, 16, 15, 9, (guchar *) "\xfc\x0f\xfc\x0f\xfc\x0f\xfe\x1f\xff\x3f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3f\xfe\x1f\xfc\x0f\xfc\x0f\xfc\x0f" },
-{ 7, 14, 3, 7, (guchar *) "\xf7\x9c\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x1c\x77" },
-{ 9, 16, 4, 8, (guchar *) "\xef\x41\xff\x01\xff\x01\x7c\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x7c\x00\xff\x01\xff\x01\xef\x01" },
-};
index 7563c5bb6ff7a22d687ed4f3ec919ca823ca8144..5f4b1deeb87acc47d59ee94a3384f985471bc92c 100644 (file)
@@ -60,6 +60,9 @@
 #ifdef GDK_RENDERING_VULKAN
 #include "vulkan/gskvulkanrenderer.h"
 #endif
+#ifdef GDK_WINDOWING_MACOS
+#include <gdk/macos/gdkmacos.h>
+#endif
 
 typedef struct
 {
@@ -555,6 +558,10 @@ get_renderer_for_backend (GdkSurface *surface)
   if (GDK_IS_BROADWAY_SURFACE (surface))
     return GSK_TYPE_BROADWAY_RENDERER;
 #endif
+#ifdef GDK_WINDOWING_MACOS
+  if (GDK_IS_MACOS_SURFACE (surface))
+    return GSK_TYPE_GL_RENDERER;
+#endif
 
   return G_TYPE_INVALID;
 }
index c5180662b41bc4b5b4b974d138c787d94614ff42..e882dc20e3a554081db60d28b0e8ea2ca88362df 100644 (file)
@@ -93,6 +93,7 @@ gtk_api_version = '4.0'
 x11_enabled      = get_option('x11-backend')
 wayland_enabled  = get_option('wayland-backend')
 broadway_enabled = get_option('broadway-backend')
+macos_enabled    = get_option('macos-backend')
 quartz_enabled   = get_option('quartz-backend')
 win32_enabled    = get_option('win32-backend')
 
@@ -118,6 +119,7 @@ if os_darwin
   wayland_enabled = false
 else
   quartz_enabled = false
+  macos_enabled = false
 endif
 
 if os_win32
@@ -791,7 +793,7 @@ pkgs = [ 'gtk4.pc' ]
 
 pkg_targets = ''
 display_backends = []
-foreach backend: [ 'broadway', 'quartz', 'wayland', 'win32', 'x11', ]
+foreach backend: [ 'broadway', 'quartz', 'macos', 'wayland', 'win32', 'x11', ]
   if get_variable('@0@_enabled'.format(backend))
     pkgs += ['gtk4-@0@.pc'.format(backend)]
     pkg_targets += ' ' + backend
index c14136f073aa6814a5e7298a6d6e0ea0d86c2090..f73f966d601d12ee2fd42dfeb1a44c332aad3e2b 100644 (file)
@@ -9,6 +9,8 @@ option('win32-backend', type: 'boolean', value: true,
   description : 'Enable the Windows gdk backend (only when building on Windows)')
 option('quartz-backend', type: 'boolean', value: true,
   description : 'Enable the macOS gdk backend (only when building on macOS)')
+option('macos-backend', type: 'boolean', value: true,
+  description : 'Enable the macOS gdk backend (only when building on macOS)')
 
 # Media backends
 option('media', type: 'string', value: 'gstreamer',